aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.builds/freebsd.yml45
-rw-r--r--.builds/openbsd.yml49
-rw-r--r--.cirrus.yml29
-rw-r--r--.git-blame-ignore-revs3
-rw-r--r--.github/labeler.yml1
-rw-r--r--.github/scripts/reviews.js10
-rwxr-xr-x.github/workflows/env.sh2
-rw-r--r--.luacheckrc7
-rw-r--r--.mailmap5
-rw-r--r--CMakeLists.txt22
-rw-r--r--CONTRIBUTING.md119
-rw-r--r--README.md1
-rw-r--r--cmake.deps/CMakeLists.txt36
-rw-r--r--cmake.deps/cmake/BuildGettext.cmake4
-rw-r--r--cmake.deps/cmake/BuildLibiconv.cmake4
-rw-r--r--cmake.deps/cmake/BuildLibtermkey.cmake58
-rw-r--r--cmake.deps/cmake/BuildLibvterm.cmake64
-rw-r--r--cmake.deps/cmake/BuildLua.cmake57
-rw-r--r--cmake.deps/cmake/BuildLuarocks.cmake83
-rw-r--r--cmake.deps/cmake/BuildLuv.cmake96
-rw-r--r--cmake.deps/cmake/BuildMsgpack.cmake55
-rw-r--r--cmake.deps/cmake/BuildTreesitter.cmake71
-rw-r--r--cmake.deps/cmake/BuildTreesitterParsers.cmake52
-rw-r--r--cmake.deps/cmake/BuildUnibilium.cmake71
-rw-r--r--cmake.deps/cmake/TreesitterParserCMakeLists.txt8
-rw-r--r--cmake.deps/patches/libvterm-Remove-VLAs-for-MSVC.patch50
-rw-r--r--cmake/GenerateVersion.cmake10
-rw-r--r--cmake/RunTests.cmake5
-rw-r--r--cmake/Util.cmake40
-rw-r--r--contrib/flake.lock12
-rw-r--r--contrib/flake.nix126
-rw-r--r--runtime/CMakeLists.txt2
-rw-r--r--runtime/autoload/dist/ft.vim19
-rw-r--r--runtime/autoload/man.vim529
-rw-r--r--runtime/autoload/python.vim40
-rw-r--r--runtime/autoload/usermark.vim7
-rw-r--r--runtime/autoload/userreg.vim7
-rw-r--r--runtime/colors/blue.vim18
-rw-r--r--runtime/colors/darkblue.vim8
-rw-r--r--runtime/colors/delek.vim12
-rw-r--r--runtime/colors/desert.vim8
-rw-r--r--runtime/colors/elflord.vim6
-rw-r--r--runtime/colors/evening.vim41
-rw-r--r--runtime/colors/habamax.vim8
-rw-r--r--runtime/colors/industry.vim16
-rw-r--r--runtime/colors/koehler.vim6
-rw-r--r--runtime/colors/lunaperche.vim97
-rw-r--r--runtime/colors/morning.vim8
-rw-r--r--runtime/colors/murphy.vim8
-rw-r--r--runtime/colors/pablo.vim24
-rw-r--r--runtime/colors/peachpuff.vim8
-rw-r--r--runtime/colors/quiet.vim6
-rw-r--r--runtime/colors/ron.vim6
-rw-r--r--runtime/colors/shine.vim8
-rw-r--r--runtime/colors/slate.vim8
-rw-r--r--runtime/colors/torte.vim8
-rw-r--r--runtime/colors/zellner.vim8
-rw-r--r--runtime/compiler/raco.vim14
-rw-r--r--runtime/compiler/racomake.vim14
-rw-r--r--runtime/compiler/racosetup.vim14
-rw-r--r--runtime/compiler/racotest.vim14
-rw-r--r--runtime/doc/api.txt17
-rw-r--r--runtime/doc/autocmd.txt2
-rw-r--r--runtime/doc/builtin.txt161
-rw-r--r--runtime/doc/cmdline.txt8
-rw-r--r--runtime/doc/eval.txt396
-rw-r--r--runtime/doc/filetype.txt4
-rw-r--r--runtime/doc/help.txt1
-rw-r--r--runtime/doc/indent.txt27
-rw-r--r--runtime/doc/lsp.txt57
-rw-r--r--runtime/doc/lua.txt287
-rw-r--r--runtime/doc/map.txt10
-rw-r--r--runtime/doc/options.txt154
-rw-r--r--runtime/doc/quickref.txt1
-rw-r--r--runtime/doc/syntax.txt10
-rw-r--r--runtime/doc/tagsrch.txt8
-rw-r--r--runtime/doc/treesitter.txt241
-rw-r--r--runtime/doc/ui.txt1
-rw-r--r--runtime/doc/userfunc.txt429
-rw-r--r--runtime/doc/usr_41.txt2
-rw-r--r--runtime/doc/vim_diff.txt5
-rw-r--r--runtime/doc/windows.txt15
-rw-r--r--runtime/filetype.lua2
-rw-r--r--runtime/filetype.vim49
-rw-r--r--runtime/ftplugin/gitattributes.vim13
-rw-r--r--runtime/ftplugin/gitignore.vim13
-rw-r--r--runtime/ftplugin/jsonnet.vim17
-rw-r--r--runtime/ftplugin/lua.lua3
-rw-r--r--runtime/ftplugin/lua.vim38
-rw-r--r--runtime/ftplugin/lynx.vim29
-rw-r--r--runtime/ftplugin/man.vim4
-rw-r--r--runtime/ftplugin/racket.vim82
-rw-r--r--runtime/ftplugin/sh.vim53
-rw-r--r--runtime/ftplugin/vim.vim2
-rw-r--r--runtime/ftplugin/zimbu.vim4
-rw-r--r--runtime/ftplugin/zsh.vim2
-rw-r--r--runtime/indent/json.vim3
-rw-r--r--runtime/indent/racket.vim60
-rw-r--r--runtime/indent/testdir/python.in18
-rw-r--r--runtime/indent/testdir/python.ok18
-rw-r--r--runtime/indent/testdir/runtest.vim15
-rw-r--r--runtime/indent/testdir/vim.in7
-rw-r--r--runtime/indent/testdir/vim.ok7
-rw-r--r--runtime/indent/vim.vim44
-rw-r--r--runtime/indent/yaml.vim10
-rw-r--r--runtime/lua/man.lua601
-rw-r--r--runtime/lua/vim/_meta.lua3
-rw-r--r--runtime/lua/vim/diagnostic.lua30
-rw-r--r--runtime/lua/vim/filetype.lua36
-rw-r--r--runtime/lua/vim/filetype/detect.lua13
-rw-r--r--runtime/lua/vim/inspect.lua32
-rw-r--r--runtime/lua/vim/lsp.lua93
-rw-r--r--runtime/lua/vim/lsp/buf.lua82
-rw-r--r--runtime/lua/vim/lsp/rpc.lua781
-rw-r--r--runtime/lua/vim/shared.lua25
-rw-r--r--runtime/lua/vim/treesitter.lua251
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua141
-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.lua79
-rw-r--r--runtime/lua/vim/usermark.lua68
-rw-r--r--runtime/lua/vim/userreg.lua51
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim9
-rw-r--r--runtime/plugin/man.lua34
-rw-r--r--runtime/plugin/man.vim15
-rw-r--r--runtime/plugin/matchparen.vim5
-rw-r--r--runtime/plugin/usermark.vim1
-rw-r--r--runtime/plugin/userreg.vim1
-rw-r--r--runtime/queries/c/highlights.scm2
-rw-r--r--runtime/queries/c/injections.scm3
-rw-r--r--runtime/queries/lua/highlights.scm194
-rw-r--r--runtime/queries/lua/injections.scm22
-rw-r--r--runtime/queries/vim/highlights.scm259
-rw-r--r--runtime/queries/vim/injections.scm26
-rw-r--r--runtime/syntax/gdresource.vim65
-rw-r--r--runtime/syntax/gdscript.vim105
-rw-r--r--runtime/syntax/gdshader.vim57
-rw-r--r--runtime/syntax/gitattributes.vim63
-rw-r--r--runtime/syntax/gitignore.vim29
-rw-r--r--runtime/syntax/lua.vim70
-rw-r--r--runtime/syntax/plsql.vim87
-rw-r--r--runtime/syntax/racket.vim656
-rw-r--r--runtime/syntax/sh.vim6
-rw-r--r--runtime/syntax/synload.vim2
-rw-r--r--runtime/syntax/syntax.vim7
-rw-r--r--runtime/syntax/vim.vim2
-rw-r--r--runtime/syntax/zsh.vim163
-rwxr-xr-xscripts/check-includes.py64
-rwxr-xr-xscripts/gen_vimdoc.py2
-rwxr-xr-xsrc/clint.py7
-rwxr-xr-xsrc/nvim/CMakeLists.txt7
-rw-r--r--src/nvim/api/autocmd.c4
-rw-r--r--src/nvim/api/buffer.c14
-rw-r--r--src/nvim/api/command.c35
-rw-r--r--src/nvim/api/extmark.c71
-rw-r--r--src/nvim/api/keysets.lua13
-rw-r--r--src/nvim/api/private/converter.c9
-rw-r--r--src/nvim/api/private/dispatch.h9
-rw-r--r--src/nvim/api/private/helpers.c45
-rw-r--r--src/nvim/api/private/helpers.h1
-rw-r--r--src/nvim/api/ui.c67
-rw-r--r--src/nvim/api/ui_events.in.h4
-rw-r--r--src/nvim/api/vim.c122
-rw-r--r--src/nvim/api/vimscript.c4
-rw-r--r--src/nvim/api/win_config.c105
-rw-r--r--src/nvim/api/window.c4
-rw-r--r--src/nvim/arabic.c26
-rw-r--r--src/nvim/arglist.c199
-rw-r--r--src/nvim/autocmd.c60
-rw-r--r--src/nvim/autocmd.h3
-rw-r--r--src/nvim/buffer.c91
-rw-r--r--src/nvim/buffer_defs.h599
-rw-r--r--src/nvim/buffer_updates.c8
-rw-r--r--src/nvim/change.c235
-rw-r--r--src/nvim/charset.c139
-rw-r--r--src/nvim/cmdexpand.c1220
-rw-r--r--src/nvim/cmdhist.c47
-rw-r--r--src/nvim/cmdhist.h2
-rw-r--r--src/nvim/context.c4
-rw-r--r--src/nvim/cursor.c33
-rw-r--r--src/nvim/cursor_shape.c2
-rw-r--r--src/nvim/debugger.c66
-rw-r--r--src/nvim/decoration.c18
-rw-r--r--src/nvim/decoration.h7
-rw-r--r--src/nvim/decoration_provider.c33
-rw-r--r--src/nvim/decoration_provider.h1
-rw-r--r--src/nvim/diff.c115
-rw-r--r--src/nvim/digraph.c38
-rw-r--r--src/nvim/drawline.c119
-rw-r--r--src/nvim/drawscreen.c269
-rw-r--r--src/nvim/drawscreen.h14
-rw-r--r--src/nvim/edit.c1343
-rw-r--r--src/nvim/eval.c175
-rw-r--r--src/nvim/eval.h52
-rw-r--r--src/nvim/eval.lua36
-rw-r--r--src/nvim/eval/decode.c4
-rw-r--r--src/nvim/eval/executor.c3
-rw-r--r--src/nvim/eval/funcs.c1003
-rw-r--r--src/nvim/eval/funcs.h17
-rw-r--r--src/nvim/eval/typval.c79
-rw-r--r--src/nvim/eval/typval.h29
-rw-r--r--src/nvim/eval/userfunc.c438
-rw-r--r--src/nvim/eval/userfunc.h14
-rw-r--r--src/nvim/eval/vars.c55
-rw-r--r--src/nvim/event/socket.c2
-rw-r--r--src/nvim/ex_cmds.c646
-rw-r--r--src/nvim/ex_cmds.lua6
-rw-r--r--src/nvim/ex_cmds2.c356
-rw-r--r--src/nvim/ex_cmds2.h2
-rw-r--r--src/nvim/ex_cmds_defs.h10
-rw-r--r--src/nvim/ex_docmd.c394
-rw-r--r--src/nvim/ex_eval.c671
-rw-r--r--src/nvim/ex_getln.c561
-rw-r--r--src/nvim/ex_getln.h2
-rw-r--r--src/nvim/ex_session.c4
-rw-r--r--src/nvim/extmark.c7
-rw-r--r--src/nvim/file_search.c592
-rw-r--r--src/nvim/fileio.c1079
-rw-r--r--src/nvim/fileio.h1
-rw-r--r--src/nvim/fold.c116
-rw-r--r--src/nvim/fold.h6
-rw-r--r--src/nvim/garray.c4
-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.lua8
-rw-r--r--src/nvim/generators/gen_eval.lua15
-rw-r--r--src/nvim/generators/gen_options.lua2
-rw-r--r--src/nvim/getchar.c436
-rw-r--r--src/nvim/globals.h58
-rw-r--r--src/nvim/grid.c39
-rw-r--r--src/nvim/grid.h16
-rw-r--r--src/nvim/grid_defs.h2
-rw-r--r--src/nvim/hardcopy.c644
-rw-r--r--src/nvim/hardcopy.h12
-rw-r--r--src/nvim/hashtab.c4
-rw-r--r--src/nvim/help.c95
-rw-r--r--src/nvim/highlight.c36
-rw-r--r--src/nvim/highlight.h2
-rw-r--r--src/nvim/highlight_group.c169
-rw-r--r--src/nvim/if_cscope.c197
-rw-r--r--src/nvim/indent.c135
-rw-r--r--src/nvim/indent_c.c1391
-rw-r--r--src/nvim/input.c2
-rw-r--r--src/nvim/insexpand.c2981
-rw-r--r--src/nvim/keycodes.c152
-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/converter.c13
-rw-r--r--src/nvim/lua/converter.h8
-rw-r--r--src/nvim/lua/executor.c139
-rw-r--r--src/nvim/lua/stdlib.c59
-rw-r--r--src/nvim/lua/treesitter.c95
-rw-r--r--src/nvim/macros.h6
-rw-r--r--src/nvim/main.c163
-rw-r--r--src/nvim/map.c3
-rw-r--r--src/nvim/map.h3
-rw-r--r--src/nvim/mapping.c255
-rw-r--r--src/nvim/mapping.h2
-rw-r--r--src/nvim/mark.c369
-rw-r--r--src/nvim/mark_defs.h8
-rw-r--r--src/nvim/match.c54
-rw-r--r--src/nvim/mbyte.c475
-rw-r--r--src/nvim/mbyte.h10
-rw-r--r--src/nvim/memfile.c18
-rw-r--r--src/nvim/memfile_defs.h2
-rw-r--r--src/nvim/memline.c1028
-rw-r--r--src/nvim/memline_defs.h2
-rw-r--r--src/nvim/memory.c114
-rw-r--r--src/nvim/memory.h6
-rw-r--r--src/nvim/menu.c182
-rw-r--r--src/nvim/message.c516
-rw-r--r--src/nvim/message.h10
-rw-r--r--src/nvim/mouse.c46
-rw-r--r--src/nvim/mouse.h2
-rw-r--r--src/nvim/move.c513
-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.c195
-rw-r--r--src/nvim/normal.h12
-rw-r--r--src/nvim/ops.c1653
-rw-r--r--src/nvim/ops.h30
-rw-r--r--src/nvim/option.c999
-rw-r--r--src/nvim/option_defs.h356
-rw-r--r--src/nvim/options.lua26
-rw-r--r--src/nvim/optionstr.c257
-rw-r--r--src/nvim/os/env.c35
-rw-r--r--src/nvim/os/fs.c14
-rw-r--r--src/nvim/os/input.c6
-rw-r--r--src/nvim/os/shell.c46
-rw-r--r--src/nvim/os/users.c6
-rw-r--r--src/nvim/path.c633
-rw-r--r--src/nvim/path.h4
-rw-r--r--src/nvim/plines.c185
-rw-r--r--src/nvim/plines.h13
-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.po6
-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.po6
-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.po6
-rw-r--r--src/nvim/po/uk.po6
-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.c35
-rw-r--r--src/nvim/profile.c18
-rw-r--r--src/nvim/quickfix.c206
-rw-r--r--src/nvim/regexp.c139
-rw-r--r--src/nvim/regexp_bt.c45
-rw-r--r--src/nvim/regexp_defs.h6
-rw-r--r--src/nvim/regexp_nfa.c32
-rw-r--r--src/nvim/runtime.c357
-rw-r--r--src/nvim/runtime.h3
-rw-r--r--src/nvim/screen.c116
-rw-r--r--src/nvim/search.c2515
-rw-r--r--src/nvim/shada.c34
-rw-r--r--src/nvim/sign.c335
-rw-r--r--src/nvim/sign_defs.h10
-rw-r--r--src/nvim/spell.c680
-rw-r--r--src/nvim/spell_defs.h10
-rw-r--r--src/nvim/spellfile.c502
-rw-r--r--src/nvim/spellsuggest.c171
-rw-r--r--src/nvim/state.c2
-rw-r--r--src/nvim/statusline.c27
-rw-r--r--src/nvim/strings.c154
-rw-r--r--src/nvim/syntax.c1701
-rw-r--r--src/nvim/tag.c762
-rw-r--r--src/nvim/tag.h2
-rw-r--r--src/nvim/terminal.c48
-rw-r--r--src/nvim/testdir/runtest.vim15
-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.vim11
-rw-r--r--src/nvim/testdir/test_cmdline.vim143
-rw-r--r--src/nvim/testdir/test_comments.vim277
-rw-r--r--src/nvim/testdir/test_cursor_func.vim24
-rw-r--r--src/nvim/testdir/test_debugger.vim19
-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_eval_stuff.vim40
-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.vim65
-rw-r--r--src/nvim/testdir/test_fnamemodify.vim6
-rw-r--r--src/nvim/testdir/test_functions.vim106
-rw-r--r--src/nvim/testdir/test_gui.vim43
-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.vim34
-rw-r--r--src/nvim/testdir/test_maparg.vim35
-rw-r--r--src/nvim/testdir/test_normal.vim1
-rw-r--r--src/nvim/testdir/test_options.vim66
-rw-r--r--src/nvim/testdir/test_preview.vim7
-rw-r--r--src/nvim/testdir/test_profile.vim6
-rw-r--r--src/nvim/testdir/test_quickfix.vim6
-rw-r--r--src/nvim/testdir/test_quotestar.vim5
-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_usercommands.vim4
-rw-r--r--src/nvim/testdir/test_viminfo.vim21
-rw-r--r--src/nvim/testdir/test_vimscript.vim23
-rw-r--r--src/nvim/testdir/test_window_cmd.vim55
-rw-r--r--src/nvim/testing.c36
-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.c26
-rw-r--r--src/nvim/tui/terminfo.c4
-rw-r--r--src/nvim/tui/tui.c27
-rw-r--r--src/nvim/types.h11
-rw-r--r--src/nvim/ui.c14
-rw-r--r--src/nvim/ui.h7
-rw-r--r--src/nvim/ui_bridge.c4
-rw-r--r--src/nvim/ui_client.c2
-rw-r--r--src/nvim/ui_compositor.c87
-rw-r--r--src/nvim/undo.c48
-rw-r--r--src/nvim/undo_defs.h4
-rw-r--r--src/nvim/usercmd.c46
-rw-r--r--src/nvim/usercmd.h6
-rw-r--r--src/nvim/version.c31
-rw-r--r--src/nvim/vim.h33
-rw-r--r--src/nvim/viml/parser/expressions.c9
-rw-r--r--src/nvim/viml/parser/parser.h4
-rw-r--r--src/nvim/window.c791
-rw-r--r--src/nvim/window.h27
-rw-r--r--src/nvim/yankmap.c43
-rw-r--r--src/nvim/yankmap.h24
-rw-r--r--test/functional/api/command_spec.lua60
-rw-r--r--test/functional/api/highlight_spec.lua5
-rw-r--r--test/functional/api/keymap_spec.lua42
-rw-r--r--test/functional/api/server_notifications_spec.lua4
-rw-r--r--test/functional/api/vim_spec.lua101
-rw-r--r--test/functional/autocmd/winscrolled_spec.lua14
-rw-r--r--test/functional/core/fileio_spec.lua7
-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.lua8
-rw-r--r--test/functional/ex_cmds/swapfile_preserve_recover_spec.lua124
-rw-r--r--test/functional/ex_cmds/write_spec.lua7
-rw-r--r--test/functional/helpers.lua9
-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.lua31
-rw-r--r--test/functional/lua/ui_event_spec.lua108
-rw-r--r--test/functional/lua/vim_spec.lua51
-rw-r--r--test/functional/plugin/lsp_spec.lua110
-rw-r--r--test/functional/plugin/man_spec.lua21
-rw-r--r--test/functional/terminal/altscreen_spec.lua10
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua4
-rw-r--r--test/functional/terminal/tui_spec.lua245
-rw-r--r--test/functional/treesitter/highlight_spec.lua126
-rw-r--r--test/functional/treesitter/language_spec.lua38
-rw-r--r--test/functional/treesitter/node_spec.lua54
-rw-r--r--test/functional/treesitter/parser_spec.lua3
-rw-r--r--test/functional/treesitter/utils_spec.lua31
-rw-r--r--test/functional/ui/decorations_spec.lua86
-rw-r--r--test/functional/ui/highlight_spec.lua52
-rw-r--r--test/functional/ui/messages_spec.lua6
-rw-r--r--test/functional/ui/mouse_spec.lua15
-rw-r--r--test/functional/ui/multigrid_spec.lua11
-rw-r--r--test/functional/ui/options_spec.lua7
-rw-r--r--test/functional/ui/popupmenu_spec.lua127
-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/executable_spec.lua6
-rw-r--r--test/functional/vimscript/exepath_spec.lua6
-rw-r--r--test/functional/vimscript/input_spec.lua77
-rw-r--r--test/functional/vimscript/map_functions_spec.lua42
-rw-r--r--test/helpers.lua5
-rw-r--r--test/unit/message_spec.lua2
-rw-r--r--test/unit/path_spec.lua4
473 files changed, 29626 insertions, 23434 deletions
diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml
deleted file mode 100644
index 4be49fd153..0000000000
--- a/.builds/freebsd.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-image: freebsd/latest
-
-packages:
-- cmake
-- gmake
-- ninja
-- libtool
-- automake
-- pkgconf
-- unzip
-- wget
-- gettext
-- python
-- libffi
-- gdb
-
-sources:
-- https://github.com/neovim/neovim
-
-environment:
- SOURCEHUT: 1
- LANG: en_US.UTF-8
- CMAKE_EXTRA_FLAGS: -DCI_BUILD=ON -DMIN_LOG_LEVEL=3
-
-tasks:
-- should-run: |
- if ! git -C neovim diff --name-only HEAD^! | grep -E -v "^(.github|runtime/doc/.*)" >/dev/null; then
- echo "Skipping build because only ignored files were changed"
- complete-build
- fi
-- build-deps: |
- cd neovim
- gmake deps
-- build: |
- cd neovim
- gmake CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="${CMAKE_EXTRA_FLAGS}" nvim
-- functionaltest: |
- cd neovim
- gmake functionaltest
-- unittest: |
- cd neovim
- gmake unittest
-- oldtest: |
- cd neovim
- gmake oldtest
diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml
deleted file mode 100644
index b5799e424b..0000000000
--- a/.builds/openbsd.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-# sourcehut CI: https://builds.sr.ht/~jmk/neovim
-
-image: openbsd/latest
-
-packages:
-- autoconf-2.71
-- automake-1.16.3
-- cmake
-- gettext-runtime
-- gettext-tools
-- gmake
-- libtool
-- ninja
-- unzip-6.0p14
-- gdb
-
-sources:
-- https://github.com/neovim/neovim
-
-environment:
- SOURCEHUT: 1
- LC_CTYPE: en_US.UTF-8
- CMAKE_EXTRA_FLAGS: -DCI_BUILD=ON -DMIN_LOG_LEVEL=3
-
-tasks:
-- should-run: |
- if ! git -C neovim diff --name-only HEAD^! | grep -E -v "^(.github|runtime/doc/.*)" >/dev/null; then
- echo "Skipping build because only ignored files were changed"
- complete-build
- fi
-- build-deps: |
- export AUTOCONF_VERSION=2.71
- export AUTOMAKE_VERSION=1.16
- mkdir neovim/.deps
- cd neovim/.deps
- cmake -G Ninja ../cmake.deps/
- cmake --build . --config RelWithDebInfo
-- build: |
- mkdir neovim/build
- cd neovim/build
- cmake -G Ninja $CMAKE_EXTRA_FLAGS ..
- cmake --build . --config RelWithDebInfo
- ./bin/nvim --version
-- functionaltest: |
- cd neovim/build
- cmake --build . --config RelWithDebInfo --target functionaltest
-- oldtest: |
- cd neovim
- gmake oldtest
diff --git a/.cirrus.yml b/.cirrus.yml
new file mode 100644
index 0000000000..af67170235
--- /dev/null
+++ b/.cirrus.yml
@@ -0,0 +1,29 @@
+env:
+ CIRRUS_CLONE_DEPTH: '1'
+ LANG: en_US.UTF-8
+ CMAKE_EXTRA_FLAGS: -DCI_BUILD=ON -DMIN_LOG_LEVEL=3
+
+freebsd_task:
+ name: FreeBSD
+ only_if: $BRANCH != "master"
+ freebsd_instance:
+ image_family: freebsd-13-1
+ timeout_in: 30m
+ install_script:
+ - pkg update -f
+ - pkg install -y cmake gmake ninja libtool automake pkgconf unzip wget gettext python libffi git
+ build_deps_script:
+ - gmake deps
+ build_script:
+ - gmake CMAKE_EXTRA_FLAGS="${CMAKE_EXTRA_FLAGS}" nvim
+ workaround_script:
+ # Run tests as user "cirrus" instead of root. This is required for the
+ # permission-related tests to work correctly.
+ - pw useradd cirrus -m
+ - chown -R cirrus:cirrus .
+ functionaltest_script:
+ - sudo -u cirrus gmake functionaltest
+ unittest_script:
+ - sudo -u cirrus gmake unittest
+ oldtest_script:
+ - sudo -u cirrus gmake oldtest
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 23c7862b99..b9830dd2fd 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -50,6 +50,9 @@ ee031eb5256bb83e0d6add2bae6fd943a4186ffe
aefdc6783cb77f09786542c90901a9e7120bea42
aa4f9c5341f5280f16cce0630ea54b84eef717b3
0adc66171a355a12494d87ebb767d509540c7ef9
+93f24403f8cc760ff47979c596976b53a8b16358
+1ffd527c837fb2465c9659273bbe5447a1352db2
+2498e9feb025361576603a0101c86393d211e31e
# typos
d238b8f6003d34cae7f65ff7585b48a2cd9449fb
diff --git a/.github/labeler.yml b/.github/labeler.yml
index e86c7aabe8..b4f6f054cb 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -13,6 +13,7 @@
- src/nvim/lua/treesitter.*
- runtime/lua/vim/treesitter.lua
- runtime/lua/vim/treesitter/*
+ - runtime/queries/**/*
"diagnostic":
- runtime/lua/vim/diagnostic.lua
diff --git a/.github/scripts/reviews.js b/.github/scripts/reviews.js
index 6e9a829353..c76f25b7da 100644
--- a/.github/scripts/reviews.js
+++ b/.github/scripts/reviews.js
@@ -9,15 +9,16 @@ module.exports = async ({github, context}) => {
const reviewers = new Set()
if (labels.includes('api')) {
reviewers.add("bfredl")
- reviewers.add("gpanders")
reviewers.add("muniter")
}
if (labels.includes('build')) {
reviewers.add("jamessan")
+ reviewers.add("justinmk")
}
if (labels.includes('ci')) {
+ reviewers.add("dundargoc")
reviewers.add("jamessan")
}
@@ -54,17 +55,14 @@ module.exports = async ({github, context}) => {
reviewers.add("gpanders")
}
- if (labels.includes('gui')) {
- reviewers.add("glacambre")
- reviewers.add("smolck")
- }
-
if (labels.includes('lsp')) {
reviewers.add("mfussenegger")
+ reviewers.add("glepnir")
}
if (labels.includes('treesitter')) {
reviewers.add("bfredl")
+ reviewers.add("clason")
reviewers.add("vigoux")
}
diff --git a/.github/workflows/env.sh b/.github/workflows/env.sh
index 061588da1a..da70d358a9 100755
--- a/.github/workflows/env.sh
+++ b/.github/workflows/env.sh
@@ -57,7 +57,7 @@ EOF
functionaltest-lua)
BUILD_FLAGS="$BUILD_FLAGS -DPREFER_LUA=ON"
FUNCTIONALTEST=functionaltest-lua
- DEPS_CMAKE_FLAGS="$DEPS_CMAKE_FLAGS -DUSE_BUNDLED_LUAJIT=OFF -DUSE_BUNDLED_TS_PARSERS=OFF"
+ DEPS_CMAKE_FLAGS="$DEPS_CMAKE_FLAGS -DUSE_BUNDLED_LUAJIT=OFF"
;;
*)
;;
diff --git a/.luacheckrc b/.luacheckrc
index 9bbd323e84..8c1f4cf41c 100644
--- a/.luacheckrc
+++ b/.luacheckrc
@@ -28,6 +28,13 @@ read_globals = {
globals = {
"vim.g",
+ "vim.b",
+ "vim.w",
+ "vim.o",
+ "vim.bo",
+ "vim.wo",
+ "vim.go",
+ "vim.env"
}
exclude_files = {
diff --git a/.mailmap b/.mailmap
index 7e154b4644..ffef9f280b 100644
--- a/.mailmap
+++ b/.mailmap
@@ -15,6 +15,8 @@ Christian Clason <c.clason@uni-graz.at> <christian.clason@uni-due.de>
Cédric Barreteau <> <cbarrete@users.noreply.github.com>
Dan Aloni <alonid@gmail.com> <dan@kernelim.com>
Daniel Hahler <git@thequod.de> <github@thequod.de>
+dundargoc <gocdundar@gmail.com> <33953936+dundargoc@users.noreply.github.com>
+dundargoc <gocdundar@gmail.com> Dundar Goc
Eisuke Kawashima <e-kwsm@users.noreply.github.com> E Kawashima
ElPiloto <luis.r.piloto@gmail.com> Luis Piloto
Eliseo Martínez <eliseomarmol@gmail.com> Eliseo Martínez
@@ -52,6 +54,7 @@ Jurica Bradaric <jbradaric@gmail.com> <jbradaric@users.noreply.github.com>
Jurica Bradaric <jbradaric@gmail.com> <jurica.bradaric@avl.com>
KillTheMule <KillTheMule@users.noreply.github.com> <github@pipsfrank.de>
Kwon-Young Choi <kwon-young.choi@hotmail.fr> Kwon-Young
+Lewis Russell <lewis6991@gmail.com> <me@lewisr.dev>
Lucas Hoffmann <l-m-h@web.de> <lucc@posteo.de>
Lucas Hoffmann <l-m-h@web.de> <lucc@users.noreply.github.com>
Marco Hinz <mh.codebro@gmail.com> <mh.codebro+github@gmail.com>
@@ -92,7 +95,7 @@ Steven Sojka <Steven.Sojka@tdameritrade.com> <steelsojka@gmail.com>
Steven Sojka <steelsojka@gmail.com> <steelsojka@users.noreply.github.com>
TJ DeVries <devries.timothyj@gmail.com> <timothydvrs1234@gmail.com>
Thomas Fehér <thomas.feher@yahoo.de> <thomasfeher@web.de>
-Thomas Vigouroux <tomvig38@gmail.com> <39092278+vigoux@users.noreply.github.com>
+Thomas Vigouroux <thomas.vigouroux@protonmail.com> <tomvig38@gmail.com> <39092278+vigoux@users.noreply.github.com>
Utkarsh Maheshwari <UtkarshME96@gmail.com> UTkarsh Maheshwari
Utkarsh Maheshwari <utkarshme96@gmail.com> <UtkarshME96@gmail.com>
VVKot <volodymyr.kot.ua@gmail.com> Volodymyr Kot
diff --git a/CMakeLists.txt b/CMakeLists.txt
index caf9658699..d3764f4a99 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,12 +6,6 @@
cmake_minimum_required(VERSION 3.10)
project(nvim C)
-if(POLICY CMP0065)
- cmake_policy(SET CMP0065 NEW)
-endif()
-if(POLICY CMP0060)
- cmake_policy(SET CMP0060 NEW)
-endif()
if(POLICY CMP0075)
cmake_policy(SET CMP0075 NEW)
endif()
@@ -102,7 +96,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# Work around some old, broken detection by CMake for knowing when to use the
# isystem flag. Apple's compilers have supported this for quite some time
# now.
- if(CMAKE_COMPILER_IS_GNUCC)
+ if(CMAKE_C_COMPILER_ID MATCHES "GNU")
set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ")
endif()
endif()
@@ -127,22 +121,12 @@ endif()
message(STATUS "CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
-# Build type.
-if(NOT CMAKE_BUILD_TYPE)
- message(STATUS "CMAKE_BUILD_TYPE not specified, default is 'Debug'")
- set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build" FORCE)
-else()
- message(STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
-endif()
+set_default_buildtype()
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(DEBUG 1)
else()
set(DEBUG 0)
endif()
-# Set available build types for CMake GUIs.
-# Other build types can still be set by -DCMAKE_BUILD_TYPE=...
-set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
- STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
# If not in a git repo (e.g., a tarball) these tokens define the complete
# version string, else they are combined with the result of `git describe`.
@@ -186,7 +170,7 @@ if(CMAKE_C_FLAGS_RELEASE MATCHES "-O3")
string(REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
endif()
-if(CMAKE_COMPILER_IS_GNUCC)
+if(CMAKE_C_COMPILER_ID MATCHES "GNU")
check_c_compiler_flag(-Og HAS_OG_FLAG)
else()
set(HAS_OG_FLAG 0)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 17622fa33a..b3adf13318 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -10,7 +10,7 @@ low-risk/isolated tasks:
- Try a [complexity:low] issue.
- Fix bugs found by [Clang](#clang-scan-build), [PVS](#pvs-studio) or
[Coverity](#coverity).
-- [Improve documentation][wiki-contribute-help]
+- [Improve documentation](#documenting)
- [Merge a Vim patch] (familiarity with Vim is *strongly* recommended)
Reporting problems
@@ -111,7 +111,7 @@ the VCS/git logs more valuable. The general structure of a commit message is:
### Automated builds (CI)
-Each pull request must pass the automated builds on [sourcehut] and [GitHub Actions].
+Each pull request must pass the automated builds on [Cirrus CI] and [GitHub Actions].
- CI builds are compiled with [`-Werror`][gcc-warnings], so compiler warnings
will fail the build.
@@ -125,20 +125,7 @@ Each pull request must pass the automated builds on [sourcehut] and [GitHub Acti
- The [lint](#lint) build checks modified lines _and their immediate
neighbors_, to encourage incrementally updating the legacy style to meet our
[style](#style). (See [#3174][3174] for background.)
-- CI for freebsd and openbsd runs on [sourcehut].
- - To get a backtrace on freebsd (after connecting via ssh):
- ```sh
- sudo pkg install tmux # If you want tmux.
- lldb build/bin/nvim -c nvim.core
-
- # To get a full backtrace:
- # 1. Rebuild with debug info.
- rm -rf nvim.core build
- gmake CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCI_BUILD=ON -DMIN_LOG_LEVEL=3" nvim
- # 2. Run the failing test to generate a new core file.
- TEST_FILE=test/functional/foo.lua gmake functionaltest
- lldb build/bin/nvim -c nvim.core
- ```
+- CI for FreeBSD runs on [Cirrus CI].
### Clang scan-build
@@ -219,10 +206,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 +232,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 +304,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
+[Cirrus CI]: https://cirrus-ci.com/github/neovim/neovim
+[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
+[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/README.md b/README.md
index e3c3c12104..7be8dc77b1 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,6 @@
[Twitter](https://twitter.com/Neovim)
[![GitHub CI](https://github.com/neovim/neovim/workflows/CI/badge.svg)](https://github.com/neovim/neovim/actions?query=workflow%3ACI+branch%3Amaster+event%3Apush)
-[![Codecov coverage](https://img.shields.io/codecov/c/github/neovim/neovim.svg)](https://codecov.io/gh/neovim/neovim)
[![Coverity Scan analysis](https://scan.coverity.com/projects/2227/badge.svg)](https://scan.coverity.com/projects/2227)
[![Clang analysis](https://neovim.io/doc/reports/clang/badge.svg)](https://neovim.io/doc/reports/clang)
[![PVS-Studio analysis](https://neovim.io/doc/reports/pvs/badge.svg)](https://neovim.io/doc/reports/pvs/PVS-studio.html.d)
diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt
index 27659b2a56..5ca610ba1f 100644
--- a/cmake.deps/CMakeLists.txt
+++ b/cmake.deps/CMakeLists.txt
@@ -2,22 +2,18 @@
cmake_minimum_required (VERSION 3.10)
project(NVIM_DEPS C)
-# Needed for: check_c_compiler_flag()
-include(CheckCCompilerFlag)
-
# Point CMake at any custom modules we may ship
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" "${PROJECT_SOURCE_DIR}/../cmake")
+include(CheckCCompilerFlag)
+include(Util)
+
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT isMultiConfig)
set(BUILD_TYPE_STRING -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
endif()
-# In Windows/MSVC CMAKE_BUILD_TYPE changes the paths/linking of the build
-# recipes (libuv, msgpack), make sure it is set
-if(NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE Release)
-endif()
+set_default_buildtype()
set(DEFAULT_MAKE_CFLAGS CFLAGS+=-g)
@@ -177,12 +173,12 @@ set(UNIBILIUM_SHA256 29815283c654277ef77a3adcc8840db79ddbb20a0f0b0c8f648bd8cd49a
set(LIBTERMKEY_URL https://www.leonerd.org.uk/code/libtermkey/libtermkey-0.22.tar.gz)
set(LIBTERMKEY_SHA256 6945bd3c4aaa83da83d80a045c5563da4edd7d0374c62c0d35aec09eb3014600)
-set(LIBVTERM_URL https://www.leonerd.org.uk/code/libvterm/libvterm-0.1.4.tar.gz)
-set(LIBVTERM_SHA256 bc70349e95559c667672fc8c55b9527d9db9ada0fb80a3beda533418d782d3dd)
+set(LIBVTERM_URL https://www.leonerd.org.uk/code/libvterm/libvterm-0.3-RC1.tar.gz)
+set(LIBVTERM_SHA256 441d1c372b84a0df12525100ab06c0366260fb4f6252abd1665ee4fa571b5134)
-set(LUV_VERSION 1.44.2-0)
-set(LUV_URL https://github.com/luvit/luv/archive/1.44.2-0.tar.gz)
-set(LUV_SHA256 44ccda27035bfe683e6325a2a93f2c254be1eb76bde6efc2bd37c56a7af7b00a)
+set(LUV_VERSION 1.44.2-1)
+set(LUV_URL https://github.com/luvit/luv/archive/1.44.2-1.tar.gz)
+set(LUV_SHA256 f8c69908e17ec8ab370253d1508e23deaecfc0c4752d2efb77e427e579501104)
set(LUA_COMPAT53_URL https://github.com/keplerproject/lua-compat-5.3/archive/v0.9.tar.gz)
set(LUA_COMPAT53_SHA256 ad05540d2d96a48725bb79a1def35cf6652a4e2ec26376e2617c8ce2baa6f416)
@@ -205,11 +201,17 @@ set(GETTEXT_SHA256 66415634c6e8c3fa8b71362879ec7575e27da43da562c798a8a2f223e6e47
set(LIBICONV_URL https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.15.tar.gz)
set(LIBICONV_SHA256 ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178)
-set(TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.20.1.tar.gz)
-set(TREESITTER_C_SHA256 ffcc2ef0eded59ad1acec9aec4f9b0c7dd209fc1a85d85f8b0e81298e3dddcc2)
+set(TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.20.2.tar.gz)
+set(TREESITTER_C_SHA256 af66fde03feb0df4faf03750102a0d265b007e5d957057b6b293c13116a70af2 )
+
+set(TREESITTER_LUA_URL https://github.com/MunifTanjim/tree-sitter-lua/archive/v0.0.12.tar.gz)
+set(TREESITTER_LUA_SHA256 b6d7c6d04e9101a2e589d25f1d61668301e776c0b8defa6eae8dd86272e9e7c3)
+
+set(TREESITTER_VIM_URL https://github.com/vigoux/tree-sitter-viml/archive/v0.2.0.tar.gz)
+set(TREESITTER_VIM_SHA256 608dcc31a7948cb66ae7f45494620e2e9face1af75598205541f80d782ec4501)
-set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/1f1b1eb4501ed0a2d195d37f7de15f72aa10acd0.tar.gz)
-set(TREESITTER_SHA256 a324bdb7ff507cd5157a36b908224d60ba638f8e3363070dd51aa383c7cbd790)
+set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.7.tar.gz)
+set(TREESITTER_SHA256 b355e968ec2d0241bbd96748e00a9038f83968f85d822ecb9940cbe4c42e182e)
if(USE_BUNDLED_UNIBILIUM)
include(BuildUnibilium)
diff --git a/cmake.deps/cmake/BuildGettext.cmake b/cmake.deps/cmake/BuildGettext.cmake
index f36c00c559..d903fbc737 100644
--- a/cmake.deps/cmake/BuildGettext.cmake
+++ b/cmake.deps/cmake/BuildGettext.cmake
@@ -23,8 +23,8 @@ if(MSVC)
-DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
-DLIBICONV_INCLUDE_DIRS=${DEPS_INSTALL_DIR}/include
-DLIBICONV_LIBRARIES=${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}libcharset${CMAKE_STATIC_LIBRARY_SUFFIX}$<SEMICOLON>${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}libiconv${CMAKE_STATIC_LIBRARY_SUFFIX}
- BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
- INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE})
+ BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>
+ INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>)
else()
message(FATAL_ERROR "Trying to build gettext in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
endif()
diff --git a/cmake.deps/cmake/BuildLibiconv.cmake b/cmake.deps/cmake/BuildLibiconv.cmake
index 434bfd6979..29168340a1 100644
--- a/cmake.deps/cmake/BuildLibiconv.cmake
+++ b/cmake.deps/cmake/BuildLibiconv.cmake
@@ -21,8 +21,8 @@ if(MSVC)
${BUILD_TYPE_STRING}
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
-DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
- INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE})
+ BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>
+ INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>)
else()
message(FATAL_ERROR "Trying to build libiconv in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
endif()
diff --git a/cmake.deps/cmake/BuildLibtermkey.cmake b/cmake.deps/cmake/BuildLibtermkey.cmake
index 66bac57d23..ee35112823 100644
--- a/cmake.deps/cmake/BuildLibtermkey.cmake
+++ b/cmake.deps/cmake/BuildLibtermkey.cmake
@@ -1,18 +1,6 @@
if(WIN32)
-ExternalProject_Add(libtermkey
- PREFIX ${DEPS_BUILD_DIR}
- URL ${LIBTERMKEY_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libtermkey
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libtermkey
- -DURL=${LIBTERMKEY_URL}
- -DEXPECTED_SHA256=${LIBTERMKEY_SHA256}
- -DTARGET=libtermkey
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/libtermkeyCMakeLists.txt
+ set(LIBTERMKEY_CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/libtermkeyCMakeLists.txt
${DEPS_BUILD_DIR}/src/libtermkey/CMakeLists.txt
COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/libtermkey
-DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
@@ -24,34 +12,32 @@ ExternalProject_Add(libtermkey
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
-DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
-DUNIBILIUM_INCLUDE_DIRS=${DEPS_INSTALL_DIR}/include
- -DUNIBILIUM_LIBRARIES=${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}unibilium${CMAKE_STATIC_LIBRARY_SUFFIX}
- BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
- INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE})
+ -DUNIBILIUM_LIBRARIES=${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}unibilium${CMAKE_STATIC_LIBRARY_SUFFIX})
+ set(LIBTERMKEY_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>)
+ set(LIBTERMKEY_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>)
else()
-find_package(PkgConfig REQUIRED)
+ find_package(PkgConfig REQUIRED)
+
+ set(LIBTERMKEY_BUILD_COMMAND "" BUILD_IN_SOURCE 1)
+ set(LIBTERMKEY_INSTALL_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER}
+ PREFIX=${DEPS_INSTALL_DIR} PKG_CONFIG_PATH=${DEPS_LIB_DIR}/pkgconfig
+ CFLAGS=-fPIC LDFLAGS+=-static ${DEFAULT_MAKE_CFLAGS} install)
+endif()
ExternalProject_Add(libtermkey
PREFIX ${DEPS_BUILD_DIR}
URL ${LIBTERMKEY_URL}
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libtermkey
DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libtermkey
- -DURL=${LIBTERMKEY_URL}
- -DEXPECTED_SHA256=${LIBTERMKEY_SHA256}
- -DTARGET=libtermkey
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- CONFIGURE_COMMAND ""
- BUILD_IN_SOURCE 1
- BUILD_COMMAND ""
- INSTALL_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER}
- PREFIX=${DEPS_INSTALL_DIR}
- PKG_CONFIG_PATH=${DEPS_LIB_DIR}/pkgconfig
- CFLAGS=-fPIC
- LDFLAGS+=-static
- ${DEFAULT_MAKE_CFLAGS}
- install)
-endif()
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libtermkey
+ -DURL=${LIBTERMKEY_URL}
+ -DEXPECTED_SHA256=${LIBTERMKEY_SHA256}
+ -DTARGET=libtermkey
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ CONFIGURE_COMMAND "${LIBTERMKEY_CONFIGURE_COMMAND}"
+ BUILD_COMMAND "${LIBTERMKEY_BUILD_COMMAND}"
+ INSTALL_COMMAND "${LIBTERMKEY_INSTALL_COMMAND}")
list(APPEND THIRD_PARTY_DEPS libtermkey)
diff --git a/cmake.deps/cmake/BuildLibvterm.cmake b/cmake.deps/cmake/BuildLibvterm.cmake
index a905733abc..8ab81e9bbe 100644
--- a/cmake.deps/cmake/BuildLibvterm.cmake
+++ b/cmake.deps/cmake/BuildLibvterm.cmake
@@ -1,43 +1,4 @@
-# BuildLibvterm(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...)
-# Failing to pass a command argument will result in no command being run
-function(BuildLibvterm)
- cmake_parse_arguments(_libvterm
- ""
- ""
- "PATCH_COMMAND;CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND"
- ${ARGN})
-
- if(NOT _libvterm_CONFIGURE_COMMAND AND NOT _libvterm_BUILD_COMMAND
- AND NOT _libvterm_INSTALL_COMMAND)
- message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
- endif()
-
- ExternalProject_Add(libvterm
- PREFIX ${DEPS_BUILD_DIR}
- URL ${LIBVTERM_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libvterm
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libvterm
- -DURL=${LIBVTERM_URL}
- -DEXPECTED_SHA256=${LIBVTERM_SHA256}
- -DTARGET=libvterm
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- PATCH_COMMAND "${_libvterm_PATCH_COMMAND}"
- BUILD_IN_SOURCE 1
- CONFIGURE_COMMAND "${_libvterm_CONFIGURE_COMMAND}"
- BUILD_COMMAND "${_libvterm_BUILD_COMMAND}"
- INSTALL_COMMAND "${_libvterm_INSTALL_COMMAND}")
-endfunction()
-
if(WIN32)
- if(MSVC)
- set(LIBVTERM_PATCH_COMMAND
- ${GIT_EXECUTABLE} -C ${DEPS_BUILD_DIR}/src/libvterm init
- COMMAND ${GIT_EXECUTABLE} -C ${DEPS_BUILD_DIR}/src/libvterm apply --ignore-whitespace
- ${CMAKE_CURRENT_SOURCE_DIR}/patches/libvterm-Remove-VLAs-for-MSVC.patch)
- endif()
set(LIBVTERM_CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/cmake/LibvtermCMakeLists.txt
${DEPS_BUILD_DIR}/src/libvterm/CMakeLists.txt
@@ -49,14 +10,13 @@ if(WIN32)
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
-DCMAKE_GENERATOR=${CMAKE_GENERATOR})
-
if(MSVC)
list(APPEND LIBVTERM_CONFIGURE_COMMAND "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_COMPILER_ARG1}")
else()
list(APPEND LIBVTERM_CONFIGURE_COMMAND "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_COMPILER_ARG1} -fPIC")
endif()
- set(LIBVTERM_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE})
- set(LIBVTERM_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE})
+ set(LIBVTERM_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>)
+ set(LIBVTERM_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>)
else()
set(LIBVTERM_INSTALL_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER}
PREFIX=${DEPS_INSTALL_DIR}
@@ -66,9 +26,21 @@ else()
install)
endif()
-BuildLibvterm(PATCH_COMMAND ${LIBVTERM_PATCH_COMMAND}
- CONFIGURE_COMMAND ${LIBVTERM_CONFIGURE_COMMAND}
- BUILD_COMMAND ${LIBVTERM_BUILD_COMMAND}
- INSTALL_COMMAND ${LIBVTERM_INSTALL_COMMAND})
+ExternalProject_Add(libvterm
+ PREFIX ${DEPS_BUILD_DIR}
+ URL ${LIBVTERM_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libvterm
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/libvterm
+ -DURL=${LIBVTERM_URL}
+ -DEXPECTED_SHA256=${LIBVTERM_SHA256}
+ -DTARGET=libvterm
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND "${LIBVTERM_CONFIGURE_COMMAND}"
+ BUILD_COMMAND "${LIBVTERM_BUILD_COMMAND}"
+ INSTALL_COMMAND "${LIBVTERM_INSTALL_COMMAND}")
list(APPEND THIRD_PARTY_DEPS libvterm)
diff --git a/cmake.deps/cmake/BuildLua.cmake b/cmake.deps/cmake/BuildLua.cmake
index a40cb7dcb2..58131a4ba7 100644
--- a/cmake.deps/cmake/BuildLua.cmake
+++ b/cmake.deps/cmake/BuildLua.cmake
@@ -1,36 +1,3 @@
-# BuildLua(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...)
-# Reusable function to build lua, wraps ExternalProject_Add.
-# Failing to pass a command argument will result in no command being run
-function(BuildLua)
- cmake_parse_arguments(_lua
- ""
- ""
- "CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND"
- ${ARGN})
-
- if(NOT _lua_CONFIGURE_COMMAND AND NOT _lua_BUILD_COMMAND
- AND NOT _lua_INSTALL_COMMAND)
- message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
- endif()
-
- ExternalProject_Add(lua
- PREFIX ${DEPS_BUILD_DIR}
- URL ${LUA_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/lua
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/lua
- -DURL=${LUA_URL}
- -DEXPECTED_SHA256=${LUA_SHA256}
- -DTARGET=lua
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- CONFIGURE_COMMAND "${_lua_CONFIGURE_COMMAND}"
- BUILD_IN_SOURCE 1
- BUILD_COMMAND "${_lua_BUILD_COMMAND}"
- INSTALL_COMMAND "${_lua_INSTALL_COMMAND}")
-endfunction()
-
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(LUA_TARGET linux)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
@@ -72,16 +39,26 @@ set(LUA_CONFIGURE_COMMAND
-e "s@\\(#define LUA_ROOT[ ]*\"\\)/usr/local@\\1${DEPS_INSTALL_DIR}@"
-i ${DEPS_BUILD_DIR}/src/lua/src/luaconf.h)
set(LUA_INSTALL_TOP_ARG "INSTALL_TOP=${DEPS_INSTALL_DIR}")
-set(LUA_BUILD_COMMAND
- ${MAKE_PRG} ${LUA_INSTALL_TOP_ARG} ${LUA_TARGET})
-set(LUA_INSTALL_COMMAND
- ${MAKE_PRG} ${LUA_INSTALL_TOP_ARG} install)
message(STATUS "Lua target is ${LUA_TARGET}")
-BuildLua(CONFIGURE_COMMAND ${LUA_CONFIGURE_COMMAND}
- BUILD_COMMAND ${LUA_BUILD_COMMAND}
- INSTALL_COMMAND ${LUA_INSTALL_COMMAND})
+ExternalProject_Add(lua
+ PREFIX ${DEPS_BUILD_DIR}
+ URL ${LUA_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/lua
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/lua
+ -DURL=${LUA_URL}
+ -DEXPECTED_SHA256=${LUA_SHA256}
+ -DTARGET=lua
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ CONFIGURE_COMMAND "${LUA_CONFIGURE_COMMAND}"
+ BUILD_IN_SOURCE 1
+ BUILD_COMMAND ${MAKE_PRG} ${LUA_INSTALL_TOP_ARG} ${LUA_TARGET}
+ INSTALL_COMMAND ${MAKE_PRG} ${LUA_INSTALL_TOP_ARG} install)
+
list(APPEND THIRD_PARTY_DEPS lua)
set(BUSTED ${DEPS_INSTALL_DIR}/bin/busted)
diff --git a/cmake.deps/cmake/BuildLuarocks.cmake b/cmake.deps/cmake/BuildLuarocks.cmake
index 73f3331176..838653e7cb 100644
--- a/cmake.deps/cmake/BuildLuarocks.cmake
+++ b/cmake.deps/cmake/BuildLuarocks.cmake
@@ -9,39 +9,6 @@
option(USE_BUNDLED_BUSTED "Use the bundled version of busted to run tests." ON)
-# BuildLuarocks(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...)
-# Reusable function to build luarocks, wraps ExternalProject_Add.
-# Failing to pass a command argument will result in no command being run
-function(BuildLuarocks)
- cmake_parse_arguments(_luarocks
- ""
- ""
- "CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND"
- ${ARGN})
-
- if(NOT _luarocks_CONFIGURE_COMMAND AND NOT _luarocks_BUILD_COMMAND
- AND NOT _luarocks_INSTALL_COMMAND)
- message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
- endif()
-
- ExternalProject_Add(luarocks
- PREFIX ${DEPS_BUILD_DIR}
- URL ${LUAROCKS_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/luarocks
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/luarocks
- -DURL=${LUAROCKS_URL}
- -DEXPECTED_SHA256=${LUAROCKS_SHA256}
- -DTARGET=luarocks
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- BUILD_IN_SOURCE 1
- CONFIGURE_COMMAND "${_luarocks_CONFIGURE_COMMAND}"
- BUILD_COMMAND "${_luarocks_BUILD_COMMAND}"
- INSTALL_COMMAND "${_luarocks_INSTALL_COMMAND}")
-endfunction()
-
# The luarocks binary location
set(LUAROCKS_BINARY ${HOSTDEPS_BIN_DIR}/luarocks)
@@ -90,10 +57,9 @@ if(UNIX)
endif()
endif()
- BuildLuarocks(
- CONFIGURE_COMMAND ${DEPS_BUILD_DIR}/src/luarocks/configure
- --prefix=${HOSTDEPS_INSTALL_DIR} --force-config ${LUAROCKS_OPTS}
- INSTALL_COMMAND ${MAKE_PRG} -j1 bootstrap)
+ set(LUAROCKS_CONFIGURE_COMMAND ${DEPS_BUILD_DIR}/src/luarocks/configure
+ --prefix=${HOSTDEPS_INSTALL_DIR} --force-config ${LUAROCKS_OPTS})
+ set(LUAROCKS_INSTALL_COMMAND ${MAKE_PRG} -j1 bootstrap)
elseif(MSVC OR MINGW)
if(MINGW)
@@ -103,7 +69,7 @@ elseif(MSVC OR MINGW)
endif()
# Ignore USE_BUNDLED_LUAJIT - always ON for native Win32
- BuildLuarocks(INSTALL_COMMAND install.bat /FORCECONFIG /NOREG /NOADMIN /Q /F
+ set(LUAROCKS_INSTALL_COMMAND install.bat /FORCECONFIG /NOREG /NOADMIN /Q /F
/LUA ${DEPS_INSTALL_DIR}
/LIB ${DEPS_LIB_DIR}
/BIN ${DEPS_BIN_DIR}
@@ -119,6 +85,23 @@ else()
message(FATAL_ERROR "Trying to build luarocks in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
endif()
+ExternalProject_Add(luarocks
+ PREFIX ${DEPS_BUILD_DIR}
+ URL ${LUAROCKS_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/luarocks
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/luarocks
+ -DURL=${LUAROCKS_URL}
+ -DEXPECTED_SHA256=${LUAROCKS_SHA256}
+ -DTARGET=luarocks
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND "${LUAROCKS_CONFIGURE_COMMAND}"
+ BUILD_COMMAND ""
+ INSTALL_COMMAND "${LUAROCKS_INSTALL_COMMAND}")
+
list(APPEND THIRD_PARTY_DEPS luarocks)
if(USE_BUNDLED_LUAJIT)
@@ -130,16 +113,14 @@ set(ROCKS_DIR ${HOSTDEPS_LIB_DIR}/luarocks/rocks-${LUA_VERSION})
# mpack
add_custom_command(OUTPUT ${ROCKS_DIR}/mpack
- COMMAND ${LUAROCKS_BINARY}
- ARGS build mpack 1.0.8-0 ${LUAROCKS_BUILDARGS}
+ COMMAND ${LUAROCKS_BINARY} build mpack 1.0.8-0 ${LUAROCKS_BUILDARGS}
DEPENDS luarocks)
add_custom_target(mpack DEPENDS ${ROCKS_DIR}/mpack)
list(APPEND THIRD_PARTY_DEPS mpack)
# lpeg
add_custom_command(OUTPUT ${ROCKS_DIR}/lpeg
- COMMAND ${LUAROCKS_BINARY}
- ARGS build lpeg 1.0.2-1 ${LUAROCKS_BUILDARGS}
+ COMMAND ${LUAROCKS_BINARY} build lpeg 1.0.2-1 ${LUAROCKS_BUILDARGS}
DEPENDS mpack)
add_custom_target(lpeg DEPENDS ${ROCKS_DIR}/lpeg)
list(APPEND THIRD_PARTY_DEPS lpeg)
@@ -147,8 +128,7 @@ list(APPEND THIRD_PARTY_DEPS lpeg)
if((NOT USE_BUNDLED_LUAJIT) AND USE_BUNDLED_LUA)
# luabitop
add_custom_command(OUTPUT ${ROCKS_DIR}/luabitop
- COMMAND ${LUAROCKS_BINARY}
- ARGS build luabitop 1.0.2-3 ${LUAROCKS_BUILDARGS}
+ COMMAND ${LUAROCKS_BINARY} build luabitop 1.0.2-3 ${LUAROCKS_BUILDARGS}
DEPENDS lpeg)
add_custom_target(luabitop DEPENDS ${ROCKS_DIR}/luabitop)
list(APPEND THIRD_PARTY_DEPS luabitop)
@@ -163,8 +143,7 @@ if(USE_BUNDLED_BUSTED)
# penlight
add_custom_command(OUTPUT ${ROCKS_DIR}/penlight
- COMMAND ${LUAROCKS_BINARY}
- ARGS build penlight 1.5.4-1 ${LUAROCKS_BUILDARGS}
+ COMMAND ${LUAROCKS_BINARY} build penlight 1.5.4-1 ${LUAROCKS_BUILDARGS}
DEPENDS ${PENLIGHT_DEPENDS})
add_custom_target(penlight DEPENDS ${ROCKS_DIR}/penlight)
@@ -177,15 +156,13 @@ if(USE_BUNDLED_BUSTED)
set(LUACHECK_EXE "${HOSTDEPS_BIN_DIR}/luacheck")
endif()
add_custom_command(OUTPUT ${BUSTED_EXE}
- COMMAND ${LUAROCKS_BINARY}
- ARGS build busted 2.0.0 ${LUAROCKS_BUILDARGS}
+ COMMAND ${LUAROCKS_BINARY} build busted 2.0.0 ${LUAROCKS_BUILDARGS}
DEPENDS penlight)
add_custom_target(busted DEPENDS ${BUSTED_EXE})
# luacheck
add_custom_command(OUTPUT ${LUACHECK_EXE}
- COMMAND ${LUAROCKS_BINARY}
- ARGS build luacheck 0.23.0-1 ${LUAROCKS_BUILDARGS}
+ COMMAND ${LUAROCKS_BINARY} build luacheck 0.23.0-1 ${LUAROCKS_BUILDARGS}
DEPENDS busted)
add_custom_target(luacheck DEPENDS ${LUACHECK_EXE})
@@ -195,8 +172,7 @@ if(USE_BUNDLED_BUSTED)
set(NVIM_CLIENT_DEPS luacheck luv-static lua-compat-5.3)
else()
add_custom_command(OUTPUT ${ROCKS_DIR}/luv
- COMMAND ${LUAROCKS_BINARY}
- ARGS build luv ${LUV_VERSION} ${LUAROCKS_BUILDARGS}
+ COMMAND ${LUAROCKS_BINARY} build luv ${LUV_VERSION} ${LUAROCKS_BUILDARGS}
DEPENDS luacheck)
add_custom_target(luv DEPENDS ${ROCKS_DIR}/luv)
set(NVIM_CLIENT_DEPS luv)
@@ -204,8 +180,7 @@ if(USE_BUNDLED_BUSTED)
# nvim-client: https://github.com/neovim/lua-client
add_custom_command(OUTPUT ${ROCKS_DIR}/nvim-client
- COMMAND ${LUAROCKS_BINARY}
- ARGS build nvim-client 0.2.4-1 ${LUAROCKS_BUILDARGS}
+ COMMAND ${LUAROCKS_BINARY} build nvim-client 0.2.4-1 ${LUAROCKS_BUILDARGS}
DEPENDS ${NVIM_CLIENT_DEPS})
add_custom_target(nvim-client DEPENDS ${ROCKS_DIR}/nvim-client)
diff --git a/cmake.deps/cmake/BuildLuv.cmake b/cmake.deps/cmake/BuildLuv.cmake
index f960b24992..9aafd9239a 100644
--- a/cmake.deps/cmake/BuildLuv.cmake
+++ b/cmake.deps/cmake/BuildLuv.cmake
@@ -1,57 +1,3 @@
-# BuildLuv(PATCH_COMMAND ... CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...)
-# Reusable function to build luv, wraps ExternalProject_Add.
-# Failing to pass a command argument will result in no command being run
-function(BuildLuv)
- cmake_parse_arguments(_luv
- ""
- ""
- "PATCH_COMMAND;CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND"
- ${ARGN})
-
- if(NOT _luv_CONFIGURE_COMMAND AND NOT _luv_BUILD_COMMAND
- AND NOT _luv_INSTALL_COMMAND)
- message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
- endif()
-
- ExternalProject_Add(lua-compat-5.3
- PREFIX ${DEPS_BUILD_DIR}
- URL ${LUA_COMPAT53_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/lua-compat-5.3
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/lua-compat-5.3
- -DURL=${LUA_COMPAT53_URL}
- -DEXPECTED_SHA256=${LUA_COMPAT53_SHA256}
- -DTARGET=lua-compat-5.3
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- PATCH_COMMAND ""
- CONFIGURE_COMMAND ""
- BUILD_COMMAND ""
- INSTALL_COMMAND "")
-
- ExternalProject_Add(luv-static
- PREFIX ${DEPS_BUILD_DIR}
- DEPENDS lua-compat-5.3
- URL ${LUV_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/luv
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/luv
- -DURL=${LUV_URL}
- -DEXPECTED_SHA256=${LUV_SHA256}
- -DTARGET=luv-static
- # The source is shared with BuildLuarocks (with USE_BUNDLED_LUV).
- -DSRC_DIR=${DEPS_BUILD_DIR}/src/luv
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- PATCH_COMMAND "${_luv_PATCH_COMMAND}"
- CONFIGURE_COMMAND "${_luv_CONFIGURE_COMMAND}"
- BUILD_COMMAND "${_luv_BUILD_COMMAND}"
- INSTALL_COMMAND "${_luv_INSTALL_COMMAND}"
- LIST_SEPARATOR |)
-endfunction()
-
set(LUV_SRC_DIR ${DEPS_BUILD_DIR}/src/luv)
set(LUV_INCLUDE_FLAGS
"-I${DEPS_INSTALL_DIR}/include -I${DEPS_INSTALL_DIR}/include/luajit-2.1")
@@ -110,15 +56,41 @@ else()
endif()
endif()
-set(LUV_BUILD_COMMAND
- ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE})
-set(LUV_INSTALL_COMMAND
- ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE})
+ExternalProject_Add(lua-compat-5.3
+ PREFIX ${DEPS_BUILD_DIR}
+ URL ${LUA_COMPAT53_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/lua-compat-5.3
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/lua-compat-5.3
+ -DURL=${LUA_COMPAT53_URL}
+ -DEXPECTED_SHA256=${LUA_COMPAT53_SHA256}
+ -DTARGET=lua-compat-5.3
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND "")
-BuildLuv(PATCH_COMMAND ${LUV_PATCH_COMMAND}
- CONFIGURE_COMMAND ${LUV_CONFIGURE_COMMAND}
- BUILD_COMMAND ${LUV_BUILD_COMMAND}
- INSTALL_COMMAND ${LUV_INSTALL_COMMAND})
+ExternalProject_Add(luv-static
+ PREFIX ${DEPS_BUILD_DIR}
+ DEPENDS lua-compat-5.3
+ URL ${LUV_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/luv
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/luv
+ -DURL=${LUV_URL}
+ -DEXPECTED_SHA256=${LUV_SHA256}
+ -DTARGET=luv-static
+ # The source is shared with BuildLuarocks (with USE_BUNDLED_LUV).
+ -DSRC_DIR=${DEPS_BUILD_DIR}/src/luv
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ CONFIGURE_COMMAND "${LUV_CONFIGURE_COMMAND}"
+ BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>
+ INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>
+ LIST_SEPARATOR |)
list(APPEND THIRD_PARTY_DEPS luv-static)
if(USE_BUNDLED_LUAJIT)
diff --git a/cmake.deps/cmake/BuildMsgpack.cmake b/cmake.deps/cmake/BuildMsgpack.cmake
index ea3fa84d7b..f79117e4b1 100644
--- a/cmake.deps/cmake/BuildMsgpack.cmake
+++ b/cmake.deps/cmake/BuildMsgpack.cmake
@@ -1,36 +1,3 @@
-# BuildMsgpack(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...)
-# Reusable function to build msgpack, wraps ExternalProject_Add.
-# Failing to pass a command argument will result in no command being run
-function(BuildMsgpack)
- cmake_parse_arguments(_msgpack
- ""
- ""
- "CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND"
- ${ARGN})
-
- if(NOT _msgpack_CONFIGURE_COMMAND AND NOT _msgpack_BUILD_COMMAND
- AND NOT _msgpack_INSTALL_COMMAND)
- message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
- endif()
-
- ExternalProject_Add(msgpack
- PREFIX ${DEPS_BUILD_DIR}
- URL ${MSGPACK_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/msgpack
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/msgpack
- -DURL=${MSGPACK_URL}
- -DEXPECTED_SHA256=${MSGPACK_SHA256}
- -DTARGET=msgpack
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- CONFIGURE_COMMAND "${_msgpack_CONFIGURE_COMMAND}"
- BUILD_COMMAND "${_msgpack_BUILD_COMMAND}"
- INSTALL_COMMAND "${_msgpack_INSTALL_COMMAND}"
- LIST_SEPARATOR |)
-endfunction()
-
set(MSGPACK_CONFIGURE_COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/msgpack
-DMSGPACK_BUILD_TESTS=OFF
-DMSGPACK_BUILD_EXAMPLES=OFF
@@ -40,9 +7,6 @@ set(MSGPACK_CONFIGURE_COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/msgpack
"-DCMAKE_C_FLAGS:STRING=${CMAKE_C_COMPILER_ARG1} -fPIC"
-DCMAKE_GENERATOR=${CMAKE_GENERATOR})
-set(MSGPACK_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE})
-set(MSGPACK_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE})
-
if(MSVC)
# Same as Unix without fPIC
set(MSGPACK_CONFIGURE_COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/msgpack
@@ -58,8 +22,21 @@ if(MSVC)
-DCMAKE_GENERATOR=${CMAKE_GENERATOR})
endif()
-BuildMsgpack(CONFIGURE_COMMAND ${MSGPACK_CONFIGURE_COMMAND}
- BUILD_COMMAND ${MSGPACK_BUILD_COMMAND}
- INSTALL_COMMAND ${MSGPACK_INSTALL_COMMAND})
+ExternalProject_Add(msgpack
+ PREFIX ${DEPS_BUILD_DIR}
+ URL ${MSGPACK_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/msgpack
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/msgpack
+ -DURL=${MSGPACK_URL}
+ -DEXPECTED_SHA256=${MSGPACK_SHA256}
+ -DTARGET=msgpack
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ CONFIGURE_COMMAND "${MSGPACK_CONFIGURE_COMMAND}"
+ BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>
+ INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>
+ LIST_SEPARATOR |)
list(APPEND THIRD_PARTY_DEPS msgpack)
diff --git a/cmake.deps/cmake/BuildTreesitter.cmake b/cmake.deps/cmake/BuildTreesitter.cmake
index 6d98f6179c..fe4e9e2c93 100644
--- a/cmake.deps/cmake/BuildTreesitter.cmake
+++ b/cmake.deps/cmake/BuildTreesitter.cmake
@@ -1,42 +1,5 @@
-# BuildTreeSitter(TARGET targetname CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...)
-function(BuildTreeSitter)
- cmake_parse_arguments(_treesitter
- "BUILD_IN_SOURCE"
- "TARGET"
- "CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND"
- ${ARGN})
-
- if(NOT _treesitter_CONFIGURE_COMMAND AND NOT _treesitter_BUILD_COMMAND
- AND NOT _treesitter_INSTALL_COMMAND)
- message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
- endif()
- if(NOT _treesitter_TARGET)
- set(_treesitter_TARGET "tree-sitter")
- endif()
-
- ExternalProject_Add(tree-sitter
- PREFIX ${DEPS_BUILD_DIR}
- URL ${TREESITTER_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/tree-sitter
- INSTALL_DIR ${DEPS_INSTALL_DIR}
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/tree-sitter
- -DURL=${TREESITTER_URL}
- -DEXPECTED_SHA256=${TREESITTER_SHA256}
- -DTARGET=tree-sitter
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- BUILD_IN_SOURCE ${_treesitter_BUILD_IN_SOURCE}
- PATCH_COMMAND ""
- CONFIGURE_COMMAND "${_treesitter_CONFIGURE_COMMAND}"
- BUILD_COMMAND "${_treesitter_BUILD_COMMAND}"
- INSTALL_COMMAND "${_treesitter_INSTALL_COMMAND}")
-endfunction()
-
if(MSVC)
- BuildTreeSitter(BUILD_IN_SOURCE
- CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
+ set(TREESITTER_CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/cmake/TreesitterCMakeLists.txt
${DEPS_BUILD_DIR}/src/tree-sitter/CMakeLists.txt
COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/tree-sitter/CMakeLists.txt
@@ -44,16 +7,32 @@ if(MSVC)
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
-DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
${BUILD_TYPE_STRING}
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
- INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE}
- )
+ -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR})
+ set(TREESITTER_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>)
+ set(TREESITTER_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>)
else()
set(TS_CFLAGS "-O3 -Wall -Wextra")
- BuildTreeSitter(BUILD_IN_SOURCE
- CONFIGURE_COMMAND ""
- BUILD_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER} CFLAGS=${TS_CFLAGS}
- INSTALL_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER} PREFIX=${DEPS_INSTALL_DIR} install)
+ set(TREESITTER_BUILD_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER} CFLAGS=${TS_CFLAGS})
+ set(TREESITTER_INSTALL_COMMAND
+ ${MAKE_PRG} CC=${DEPS_C_COMPILER} PREFIX=${DEPS_INSTALL_DIR} install)
endif()
+ExternalProject_Add(tree-sitter
+ PREFIX ${DEPS_BUILD_DIR}
+ URL ${TREESITTER_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/tree-sitter
+ INSTALL_DIR ${DEPS_INSTALL_DIR}
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/tree-sitter
+ -DURL=${TREESITTER_URL}
+ -DEXPECTED_SHA256=${TREESITTER_SHA256}
+ -DTARGET=tree-sitter
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND "${TREESITTER_CONFIGURE_COMMAND}"
+ BUILD_COMMAND "${TREESITTER_BUILD_COMMAND}"
+ INSTALL_COMMAND "${TREESITTER_INSTALL_COMMAND}")
+
list(APPEND THIRD_PARTY_DEPS tree-sitter)
diff --git a/cmake.deps/cmake/BuildTreesitterParsers.cmake b/cmake.deps/cmake/BuildTreesitterParsers.cmake
index 1ff86e89b9..dd3f4eb308 100644
--- a/cmake.deps/cmake/BuildTreesitterParsers.cmake
+++ b/cmake.deps/cmake/BuildTreesitterParsers.cmake
@@ -1,29 +1,25 @@
-ExternalProject_Add(treesitter-c
-PREFIX ${DEPS_BUILD_DIR}
-URL ${TREESITTER_C_URL}
-DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/treesitter-c
-DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/treesitter-c
- -DURL=${TREESITTER_C_URL}
- -DEXPECTED_SHA256=${TREESITTER_C_SHA256}
- -DTARGET=treesitter-c
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
-PATCH_COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/TreesitterParserCMakeLists.txt
- ${DEPS_BUILD_DIR}/src/treesitter-c/CMakeLists.txt
-CMAKE_ARGS
- -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- ${BUILD_TYPE_STRING}
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES_ALT_SEP}
- # Pass toolchain
- -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
- -DPARSERLANG=c
+function(BuildTSParser LANG TS_URL TS_SHA256 TS_CMAKE_FILE)
+ set(NAME treesitter-${LANG})
+ ExternalProject_Add(${NAME}
+ PREFIX ${DEPS_BUILD_DIR}
+ URL ${TREESITTER_C_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/${NAME}
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/${NAME}
+ -DURL=${TS_URL}
+ -DEXPECTED_SHA256=${TS_SHA256}
+ -DTARGET=${NAME}
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ PATCH_COMMAND ${CMAKE_COMMAND} -E copy
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TS_CMAKE_FILE}
+ ${DEPS_BUILD_DIR}/src/${NAME}/CMakeLists.txt
+ CMAKE_ARGS
+ -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
+ -DPARSERLANG=${LANG})
+endfunction()
-BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
-INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE}
-LIST_SEPARATOR |)
+BuildTSParser(c ${TREESITTER_C_URL} ${TREESITTER_C_SHA256} TreesitterParserCMakeLists.txt)
+BuildTSParser(lua ${TREESITTER_LUA_URL} ${TREESITTER_LUA_SHA256} TreesitterParserCMakeLists.txt)
+BuildTSParser(vim ${TREESITTER_VIM_URL} ${TREESITTER_VIM_SHA256} TreesitterParserCMakeLists.txt)
diff --git a/cmake.deps/cmake/BuildUnibilium.cmake b/cmake.deps/cmake/BuildUnibilium.cmake
index fd5d68f9a8..020f01ba0b 100644
--- a/cmake.deps/cmake/BuildUnibilium.cmake
+++ b/cmake.deps/cmake/BuildUnibilium.cmake
@@ -1,48 +1,37 @@
if(WIN32)
- ExternalProject_Add(unibilium
- PREFIX ${DEPS_BUILD_DIR}
- URL ${UNIBILIUM_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/unibilium
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/unibilium
- -DURL=${UNIBILIUM_URL}
- -DEXPECTED_SHA256=${UNIBILIUM_SHA256}
- -DTARGET=unibilium
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
+ set(UNIBILIUM_CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/cmake/UnibiliumCMakeLists.txt
${DEPS_BUILD_DIR}/src/unibilium/CMakeLists.txt
- COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/unibilium
- -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
- # Pass toolchain
- -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN}
- -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
- ${BUILD_TYPE_STRING}
- -DCMAKE_GENERATOR=${CMAKE_GENERATOR}
- BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE}
- INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config ${CMAKE_BUILD_TYPE})
+ COMMAND ${CMAKE_COMMAND} ${DEPS_BUILD_DIR}/src/unibilium
+ -DCMAKE_INSTALL_PREFIX=${DEPS_INSTALL_DIR}
+ # Pass toolchain
+ -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN}
+ -DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
+ ${BUILD_TYPE_STRING}
+ -DCMAKE_GENERATOR=${CMAKE_GENERATOR})
+ set(UNIBILIUM_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>)
+ set(UNIBILIUM_INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG>)
else()
- ExternalProject_Add(unibilium
- PREFIX ${DEPS_BUILD_DIR}
- URL ${UNIBILIUM_URL}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/unibilium
- DOWNLOAD_COMMAND ${CMAKE_COMMAND}
- -DPREFIX=${DEPS_BUILD_DIR}
- -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/unibilium
- -DURL=${UNIBILIUM_URL}
- -DEXPECTED_SHA256=${UNIBILIUM_SHA256}
- -DTARGET=unibilium
- -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
- CONFIGURE_COMMAND ""
- BUILD_IN_SOURCE 1
- BUILD_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER}
- PREFIX=${DEPS_INSTALL_DIR}
- CFLAGS=-fPIC
- LDFLAGS+=-static
- INSTALL_COMMAND ${MAKE_PRG} PREFIX=${DEPS_INSTALL_DIR} install)
+ set(UNIBILIUM_BUILD_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER}
+ PREFIX=${DEPS_INSTALL_DIR} CFLAGS=-fPIC LDFLAGS+=-static
+ BUILD_IN_SOURCE 1)
+ set(UNIBILIUM_INSTALL_COMMAND ${MAKE_PRG} PREFIX=${DEPS_INSTALL_DIR} install)
endif()
+ExternalProject_Add(unibilium
+ PREFIX ${DEPS_BUILD_DIR}
+ URL ${UNIBILIUM_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/unibilium
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/unibilium
+ -DURL=${UNIBILIUM_URL}
+ -DEXPECTED_SHA256=${UNIBILIUM_SHA256}
+ -DTARGET=unibilium
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ CONFIGURE_COMMAND "${UNIBILIUM_CONFIGURE_COMMAND}"
+ BUILD_COMMAND "${UNIBILIUM_BUILD_COMMAND}"
+ INSTALL_COMMAND "${UNIBILIUM_INSTALL_COMMAND}")
+
list(APPEND THIRD_PARTY_DEPS unibilium)
diff --git a/cmake.deps/cmake/TreesitterParserCMakeLists.txt b/cmake.deps/cmake/TreesitterParserCMakeLists.txt
index 54bc35fb8a..be07f00a37 100644
--- a/cmake.deps/cmake/TreesitterParserCMakeLists.txt
+++ b/cmake.deps/cmake/TreesitterParserCMakeLists.txt
@@ -1,10 +1,12 @@
cmake_minimum_required(VERSION 3.10)
-# some parsers have c++ scanner, problem?
-project(parser C) # CXX
+project(parser C)
+
+set(CMAKE_C_STANDARD 99)
+file(GLOB source_files src/*.c)
add_library(parser
MODULE
- src/parser.c
+ ${source_files}
)
set_target_properties(
parser
diff --git a/cmake.deps/patches/libvterm-Remove-VLAs-for-MSVC.patch b/cmake.deps/patches/libvterm-Remove-VLAs-for-MSVC.patch
deleted file mode 100644
index e999c0fa9b..0000000000
--- a/cmake.deps/patches/libvterm-Remove-VLAs-for-MSVC.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From eb386b1d82f7d07363c9133b7aa06902ccd555fe Mon Sep 17 00:00:00 2001
-Date: Tue, 27 Feb 2018 17:54:20 -0600
-Subject: [PATCH] Remove VLAs for MSVC
-
-VLAs are replaced with calls to _alloca() because MSVC does not support them.
----
- src/state.c | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
-diff --git a/src/state.c b/src/state.c
-index 84299df..f9aabb3 100644
---- a/src/state.c
-+++ b/src/state.c
-@@ -1,5 +1,6 @@
- #include "vterm_internal.h"
-
-+#include <malloc.h>
- #include <stdio.h>
- #include <string.h>
-
-@@ -236,7 +237,7 @@ static int on_text(const char bytes[], size_t len, void *user)
- VTermPos oldpos = state->pos;
-
- // We'll have at most len codepoints
-- uint32_t codepoints[len];
-+ uint32_t* codepoints = _alloca(len * sizeof(uint32_t));
- int npoints = 0;
- size_t eaten = 0;
-
-@@ -313,7 +314,7 @@ static int on_text(const char bytes[], size_t len, void *user)
-
- int width = 0;
-
-- uint32_t chars[glyph_ends - glyph_starts + 1];
-+ uint32_t* chars = _alloca((glyph_ends - glyph_starts + 1) * sizeof(uint32_t));
-
- for( ; i < glyph_ends; i++) {
- chars[i - glyph_starts] = codepoints[i];
-@@ -512,7 +513,7 @@ static int settermprop_int(VTermState *state, VTermProp prop, int v)
-
- static int settermprop_string(VTermState *state, VTermProp prop, const char *str, size_t len)
- {
-- char strvalue[len+1];
-+ char* strvalue = _alloca(len+1);
- strncpy(strvalue, str, len);
- strvalue[len] = 0;
-
---
-2.16.1.windows.4
-
diff --git a/cmake/GenerateVersion.cmake b/cmake/GenerateVersion.cmake
index 6118d8cba7..a7a72fe0bb 100644
--- a/cmake/GenerateVersion.cmake
+++ b/cmake/GenerateVersion.cmake
@@ -7,15 +7,11 @@ set(NVIM_VERSION_MEDIUM
"v${NVIM_VERSION_MAJOR}.${NVIM_VERSION_MINOR}.${NVIM_VERSION_PATCH}${NVIM_VERSION_PRERELEASE}")
execute_process(
- COMMAND git describe --first-parent --dirty
+ COMMAND git describe --first-parent --dirty --always
OUTPUT_VARIABLE GIT_TAG
- ERROR_VARIABLE ERR
- RESULT_VARIABLE RES
-)
+ RESULT_VARIABLE RES)
-if(NOT RES EQUAL 0)
- message(STATUS "Git tag extraction failed:\n" " ${GIT_TAG}${ERR}" )
- # This will only be executed once since the file will get generated afterwards.
+if(RES AND NOT RES EQUAL 0)
message(STATUS "Using NVIM_VERSION_MEDIUM: ${NVIM_VERSION_MEDIUM}")
file(WRITE "${OUTPUT}" "${NVIM_VERSION_STRING}")
return()
diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake
index e07c6dd174..86ce22de72 100644
--- a/cmake/RunTests.cmake
+++ b/cmake/RunTests.cmake
@@ -1,11 +1,6 @@
# Set LC_ALL to meet expectations of some locale-sensitive tests.
set(ENV{LC_ALL} "en_US.UTF-8")
-if(POLICY CMP0012)
- # Handle CI=true, without dev warnings.
- cmake_policy(SET CMP0012 NEW)
-endif()
-
set(ENV{VIMRUNTIME} ${WORKING_DIR}/runtime)
set(ENV{NVIM_RPLUGIN_MANIFEST} ${BUILD_DIR}/Xtest_rplugin_manifest)
set(ENV{XDG_CONFIG_HOME} ${BUILD_DIR}/Xtest_xdg/config)
diff --git a/cmake/Util.cmake b/cmake/Util.cmake
index b485f4606b..343a729305 100644
--- a/cmake/Util.cmake
+++ b/cmake/Util.cmake
@@ -143,3 +143,43 @@ function(add_glob_targets)
add_custom_target(${ARG_TARGET} DEPENDS ${touch_list})
endfunction()
+
+# Set default build type to Debug. Also limit the list of allowable build types
+# to the ones defined in variable allowableBuildTypes.
+#
+# The correct way to specify build type (for example Release) for
+# single-configuration generators (Make and Ninja) is to run
+#
+# cmake -B build -D CMAKE_BUILD_TYPE=Release
+# cmake --build build
+#
+# while for multi-configuration generators (Visual Studio, Xcode and Ninja
+# Multi-Config) is to run
+#
+# cmake -B build
+# cmake --build build --config Release
+#
+# Passing CMAKE_BUILD_TYPE for multi-config generators will now not only
+# not be used, but also generate a warning for the user.
+function(set_default_buildtype)
+ set(allowableBuildTypes Debug Release MinSizeRel RelWithDebInfo)
+
+ get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(isMultiConfig)
+ set(CMAKE_CONFIGURATION_TYPES ${allowableBuildTypes} PARENT_SCOPE)
+ if(CMAKE_BUILD_TYPE)
+ message(WARNING "CMAKE_BUILD_TYPE specified which is ignored on \
+ multi-configuration generators. Defaulting to Debug build type.")
+ endif()
+ else()
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowableBuildTypes}")
+ if(NOT CMAKE_BUILD_TYPE)
+ message(STATUS "CMAKE_BUILD_TYPE not specified, default is 'Debug'")
+ set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE)
+ elseif(NOT CMAKE_BUILD_TYPE IN_LIST allowableBuildTypes)
+ message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
+ else()
+ message(STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
+ endif()
+ endif()
+endfunction()
diff --git a/contrib/flake.lock b/contrib/flake.lock
index b72e1f8d5f..48f5f0115a 100644
--- a/contrib/flake.lock
+++ b/contrib/flake.lock
@@ -2,11 +2,11 @@
"nodes": {
"flake-utils": {
"locked": {
- "lastModified": 1644229661,
- "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
+ "lastModified": 1659877975,
+ "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
- "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
+ "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
@@ -17,11 +17,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1646254136,
- "narHash": "sha256-8nQx02tTzgYO21BP/dy5BCRopE8OwE8Drsw98j+Qoaw=",
+ "lastModified": 1662019588,
+ "narHash": "sha256-oPEjHKGGVbBXqwwL+UjsveJzghWiWV0n9ogo1X6l4cw=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "3e072546ea98db00c2364b81491b893673267827",
+ "rev": "2da64a81275b68fdad38af669afeda43d401e94b",
"type": "github"
},
"original": {
diff --git a/contrib/flake.nix b/contrib/flake.nix
index a1072674ba..ef3174dda1 100644
--- a/contrib/flake.nix
+++ b/contrib/flake.nix
@@ -23,24 +23,25 @@
});
# a development binary to help debug issues
- neovim-debug = let
- stdenv = if pkgs.stdenv.isLinux then pkgs.llvmPackages_latest.stdenv else pkgs.stdenv;
- in
+ neovim-debug =
+ let
+ stdenv = if pkgs.stdenv.isLinux then pkgs.llvmPackages_latest.stdenv else pkgs.stdenv;
+ in
((neovim.override {
- lua = pkgs.luajit;
- inherit stdenv;
- }).overrideAttrs (oa: {
+ lua = pkgs.luajit;
+ inherit stdenv;
+ }).overrideAttrs (oa: {
- dontStrip = true;
- NIX_CFLAGS_COMPILE = " -ggdb -Og";
+ dontStrip = true;
+ NIX_CFLAGS_COMPILE = " -ggdb -Og";
- cmakeBuildType = "Debug";
- cmakeFlags = oa.cmakeFlags ++ [
- "-DMIN_LOG_LEVEL=0"
- ];
+ cmakeBuildType = "Debug";
+ cmakeFlags = oa.cmakeFlags ++ [
+ "-DMIN_LOG_LEVEL=0"
+ ];
- disallowedReferences = [];
- }));
+ disallowedReferences = [ ];
+ }));
# for neovim developers, beware of the slow binary
neovim-developer =
@@ -68,70 +69,71 @@
inherit system;
};
- pythonEnv = pkgs.python3.withPackages(ps: [
+ lua = pkgs.lua5_1;
+
+ pythonEnv = pkgs.python3.withPackages (ps: [
ps.msgpack
- ps.flake8 # for 'make pylint'
+ ps.flake8 # for 'make pylint'
]);
in
rec {
packages = with pkgs; {
+ default = neovim;
inherit neovim neovim-debug neovim-developer;
};
checks = {
- pylint = pkgs.runCommandNoCC "pylint" {
- nativeBuildInputs = [ pythonEnv ];
- preferLocalBuild = true;
+ pylint = pkgs.runCommandNoCC "pylint"
+ {
+ nativeBuildInputs = [ pythonEnv ];
+ preferLocalBuild = true;
} "make -C ${./..} pylint > $out";
- shlint = pkgs.runCommandNoCC "shlint" {
- nativeBuildInputs = [ pkgs.shellcheck ];
- preferLocalBuild = true;
+ shlint = pkgs.runCommandNoCC "shlint"
+ {
+ nativeBuildInputs = [ pkgs.shellcheck ];
+ preferLocalBuild = true;
} "make -C ${./..} shlint > $out";
};
+ # kept for backwards-compatibility
defaultPackage = pkgs.neovim;
- apps = {
- nvim = flake-utils.lib.mkApp { drv = pkgs.neovim; name = "nvim"; };
- nvim-debug = flake-utils.lib.mkApp { drv = pkgs.neovim-debug; name = "nvim"; };
- };
-
- defaultApp = apps.nvim;
-
- devShell = let
- in
- pkgs.neovim-developer.overrideAttrs(oa: {
-
- buildInputs = with pkgs; oa.buildInputs ++ [
- cmake
- pythonEnv
- include-what-you-use # for scripts/check-includes.py
- jq # jq for scripts/vim-patch.sh -r
- shellcheck # for `make shlint`
- doxygen # for script/gen_vimdoc.py
- clang-tools # for clangd to find the correct headers
- ];
+ devShells = {
+ default = pkgs.neovim-developer.overrideAttrs (oa: {
+
+ buildInputs = with pkgs; oa.buildInputs ++ [
+ cmake
+ lua.pkgs.luacheck
+ sumneko-lua-language-server
+ pythonEnv
+ include-what-you-use # for scripts/check-includes.py
+ jq # jq for scripts/vim-patch.sh -r
+ shellcheck # for `make shlint`
+ doxygen # for script/gen_vimdoc.py
+ clang-tools # for clangd to find the correct headers
+ ];
- shellHook = oa.shellHook + ''
- export NVIM_PYTHON_LOG_LEVEL=DEBUG
- export NVIM_LOG_FILE=/tmp/nvim.log
- export ASAN_SYMBOLIZER_PATH=${pkgs.llvm_11}/bin/llvm-symbolizer
-
- # ASAN_OPTIONS=detect_leaks=1
- export ASAN_OPTIONS="log_path=./test.log:abort_on_error=1"
- export UBSAN_OPTIONS=print_stacktrace=1
- mkdir -p build/runtime/parser
- # nvim looks into CMAKE_INSTALL_DIR. Hack to avoid errors
- # when running the functionaltests
- mkdir -p outputs/out/share/nvim/syntax
- touch outputs/out/share/nvim/syntax/syntax.vim
-
- # for treesitter functionaltests
- mkdir -p runtime/parser
- cp -f ${pkgs.tree-sitter.builtGrammars.tree-sitter-c}/parser runtime/parser/c.so
- '';
- });
- });
+ shellHook = oa.shellHook + ''
+ export NVIM_PYTHON_LOG_LEVEL=DEBUG
+ export NVIM_LOG_FILE=/tmp/nvim.log
+ export ASAN_SYMBOLIZER_PATH=${pkgs.llvm_11}/bin/llvm-symbolizer
+
+ # ASAN_OPTIONS=detect_leaks=1
+ export ASAN_OPTIONS="log_path=./test.log:abort_on_error=1"
+ export UBSAN_OPTIONS=print_stacktrace=1
+ mkdir -p build/runtime/parser
+ # nvim looks into CMAKE_INSTALL_DIR. Hack to avoid errors
+ # when running the functionaltests
+ mkdir -p outputs/out/share/nvim/syntax
+ touch outputs/out/share/nvim/syntax/syntax.vim
+
+ # for treesitter functionaltests
+ mkdir -p runtime/parser
+ cp -f ${pkgs.tree-sitter.builtGrammars.tree-sitter-c}/parser runtime/parser/c.so
+ '';
+ });
+ };
+ });
}
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index e0a0b34d28..b42b1de54b 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -123,7 +123,7 @@ foreach(PROG ${RUNTIME_PROGRAMS})
endforeach()
globrecurse_wrapper(RUNTIME_FILES ${CMAKE_CURRENT_SOURCE_DIR}
- *.vim *.lua *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json)
+ *.vim *.lua *.scm *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json)
foreach(F ${RUNTIME_FILES})
get_filename_component(BASEDIR ${F} DIRECTORY)
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim
index 77140d62b1..7333e5a7e7 100644
--- a/runtime/autoload/dist/ft.vim
+++ b/runtime/autoload/dist/ft.vim
@@ -468,7 +468,7 @@ endfunc
" Returns true if file content looks like LambdaProlog module
func IsLProlog()
- " skip apparent comments and blank lines, what looks like
+ " skip apparent comments and blank lines, what looks like
" LambdaProlog comment may be RAPID header
let l = nextnonblank(1)
while l > 0 && l < line('$') && getline(l) =~ '^\s*%' " LambdaProlog comment
@@ -877,6 +877,23 @@ func dist#ft#FTsig()
endif
endfunc
+" This function checks the first 100 lines of files matching "*.sil" to
+" resolve detection between Swift Intermediate Language and SILE.
+func dist#ft#FTsil()
+ for lnum in range(1, [line('$'), 100]->min())
+ let line = getline(lnum)
+ if line =~ '^\s*[\\%]'
+ setf sile
+ return
+ elseif line =~ '^\s*\S'
+ setf sil
+ return
+ endif
+ endfor
+ " no clue, default to "sil"
+ setf sil
+endfunc
+
func dist#ft#FTsys()
if exists("g:filetype_sys")
exe "setf " .. g:filetype_sys
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
deleted file mode 100644
index b8a73a64c9..0000000000
--- a/runtime/autoload/man.vim
+++ /dev/null
@@ -1,529 +0,0 @@
-" Maintainer: Anmol Sethi <hi@nhooyr.io>
-
-if exists('s:loaded_man')
- finish
-endif
-let s:loaded_man = 1
-
-let s:find_arg = '-w'
-let s:localfile_arg = v:true " Always use -l if possible. #6683
-
-function! man#init() abort
- try
- " Check for -l support.
- call s:get_page(s:get_path('', 'man'))
- catch /command error .*/
- let s:localfile_arg = v:false
- endtry
-endfunction
-
-function! man#open_page(count, mods, ...) abort
- if a:0 > 2
- call s:error('too many arguments')
- return
- elseif a:0 == 0
- let ref = &filetype ==# 'man' ? expand('<cWORD>') : expand('<cword>')
- if empty(ref)
- call s:error('no identifier under cursor')
- return
- endif
- elseif a:0 ==# 1
- let ref = a:1
- else
- " Combine the name and sect into a manpage reference so that all
- " verification/extraction can be kept in a single function.
- " If a:2 is a reference as well, that is fine because it is the only
- " reference that will match.
- let ref = a:2.'('.a:1.')'
- endif
- try
- let [sect, name] = s:extract_sect_and_name_ref(ref)
- if a:count >= 0
- let sect = string(a:count)
- endif
- let path = s:verify_exists(sect, name)
- let [sect, name] = s:extract_sect_and_name_path(path)
- catch
- call s:error(v:exception)
- return
- endtry
-
- let [l:buf, l:save_tfu] = [bufnr(), &tagfunc]
- try
- setlocal tagfunc=man#goto_tag
- let l:target = l:name . '(' . l:sect . ')'
- if a:mods !~# 'tab' && s:find_man()
- execute 'silent keepalt tag' l:target
- else
- execute 'silent keepalt' a:mods 'stag' l:target
- endif
- call s:set_options(v:false)
- finally
- call setbufvar(l:buf, '&tagfunc', l:save_tfu)
- endtry
-
- let b:man_sect = sect
-endfunction
-
-" Called when a man:// buffer is opened.
-function! man#read_page(ref) abort
- try
- let [sect, name] = s:extract_sect_and_name_ref(a:ref)
- let path = s:verify_exists(sect, name)
- let [sect, name] = s:extract_sect_and_name_path(path)
- let page = s:get_page(path)
- catch
- call s:error(v:exception)
- return
- endtry
- let b:man_sect = sect
- call s:put_page(page)
-endfunction
-
-" Handler for s:system() function.
-function! s:system_handler(jobid, data, event) dict abort
- if a:event is# 'stdout' || a:event is# 'stderr'
- let self[a:event] .= join(a:data, "\n")
- else
- let self.exit_code = a:data
- endif
-endfunction
-
-" Run a system command and timeout after 30 seconds.
-function! s:system(cmd, ...) abort
- let opts = {
- \ 'stdout': '',
- \ 'stderr': '',
- \ 'exit_code': 0,
- \ 'on_stdout': function('s:system_handler'),
- \ 'on_stderr': function('s:system_handler'),
- \ 'on_exit': function('s:system_handler'),
- \ }
- let jobid = jobstart(a:cmd, opts)
-
- if jobid < 1
- throw printf('command error %d: %s', jobid, join(a:cmd))
- endif
-
- let res = jobwait([jobid], 30000)
- if res[0] == -1
- try
- call jobstop(jobid)
- throw printf('command timed out: %s', join(a:cmd))
- catch /^Vim(call):E900:/
- endtry
- elseif res[0] == -2
- throw printf('command interrupted: %s', join(a:cmd))
- endif
- if opts.exit_code != 0
- throw printf("command error (%d) %s: %s", jobid, join(a:cmd), substitute(opts.stderr, '\_s\+$', '', &gdefault ? '' : 'g'))
- endif
-
- return opts.stdout
-endfunction
-
-function! s:set_options(pager) abort
- setlocal noswapfile buftype=nofile bufhidden=hide
- setlocal nomodified readonly nomodifiable
- let b:pager = a:pager
- setlocal filetype=man
-endfunction
-
-function! s:get_page(path) abort
- " Disable hard-wrap by using a big $MANWIDTH (max 1000 on some systems #9065).
- " Soft-wrap: ftplugin/man.vim sets wrap/breakindent/….
- " Hard-wrap: driven by `man`.
- let manwidth = !get(g:, 'man_hardwrap', 1) ? 999 : (empty($MANWIDTH) ? winwidth(0) : $MANWIDTH)
- " Force MANPAGER=cat to ensure Vim is not recursively invoked (by man-db).
- " http://comments.gmane.org/gmane.editors.vim.devel/29085
- " Set MAN_KEEP_FORMATTING so Debian man doesn't discard backspaces.
- let cmd = ['env', 'MANPAGER=cat', 'MANWIDTH='.manwidth, 'MAN_KEEP_FORMATTING=1', 'man']
- return s:system(cmd + (s:localfile_arg ? ['-l', a:path] : [a:path]))
-endfunction
-
-function! s:put_page(page) abort
- setlocal modifiable noreadonly noswapfile
- silent keepjumps %delete _
- silent put =a:page
- while getline(1) =~# '^\s*$'
- silent keepjumps 1delete _
- endwhile
- " XXX: nroff justifies text by filling it with whitespace. That interacts
- " badly with our use of $MANWIDTH=999. Hack around this by using a fixed
- " size for those whitespace regions.
- silent! keeppatterns keepjumps %s/\s\{199,}/\=repeat(' ', 10)/g
- 1
- lua require("man").highlight_man_page()
- call s:set_options(v:false)
-endfunction
-
-function! man#show_toc() abort
- let bufname = bufname('%')
- let info = getloclist(0, {'winid': 1})
- if !empty(info) && getwinvar(info.winid, 'qf_toc') ==# bufname
- lopen
- return
- endif
-
- let toc = []
- let lnum = 2
- let last_line = line('$') - 1
- while lnum && lnum < last_line
- let text = getline(lnum)
- if text =~# '^\%( \{3\}\)\=\S.*$'
- " if text is a section title
- call add(toc, {'bufnr': bufnr('%'), 'lnum': lnum, 'text': text})
- elseif text =~# '^\s\+\%(+\|-\)\S\+'
- " if text is a flag title. we strip whitespaces and prepend two
- " spaces to have a consistent format in the loclist.
- let text = ' ' .. substitute(text, '^\s*\(.\{-}\)\s*$', '\1', '')
- call add(toc, {'bufnr': bufnr('%'), 'lnum': lnum, 'text': text})
- endif
- let lnum = nextnonblank(lnum + 1)
- endwhile
-
- call setloclist(0, toc, ' ')
- call setloclist(0, [], 'a', {'title': 'Man TOC'})
- lopen
- let w:qf_toc = bufname
-endfunction
-
-" attempt to extract the name and sect out of 'name(sect)'
-" otherwise just return the largest string of valid characters in ref
-function! s:extract_sect_and_name_ref(ref) abort
- if a:ref[0] ==# '-' " try ':Man -pandoc' with this disabled.
- throw 'manpage name cannot start with ''-'''
- endif
- let ref = matchstr(a:ref, '[^()]\+([^()]\+)')
- if empty(ref)
- let name = matchstr(a:ref, '[^()]\+')
- if empty(name)
- throw 'manpage reference cannot contain only parentheses'
- endif
- return ['', s:spaces_to_underscores(name)]
- endif
- let left = split(ref, '(')
- " see ':Man 3X curses' on why tolower.
- " TODO(nhooyr) Not sure if this is portable across OSs
- " but I have not seen a single uppercase section.
- return [tolower(split(left[1], ')')[0]), s:spaces_to_underscores(left[0])]
-endfunction
-
-" replace spaces in a man page name with underscores
-" intended for PostgreSQL, which has man pages like 'CREATE_TABLE(7)';
-" while editing SQL source code, it's nice to visually select 'CREATE TABLE'
-" and hit 'K', which requires this transformation
-function! s:spaces_to_underscores(str)
- return substitute(a:str, ' ', '_', 'g')
-endfunction
-
-function! s:get_path(sect, name) abort
- " Some man implementations (OpenBSD) return all available paths from the
- " search command. Previously, this function would simply select the first one.
- "
- " However, some searches will report matches that are incorrect:
- " man -w strlen may return string.3 followed by strlen.3, and therefore
- " selecting the first would get us the wrong page. Thus, we must find the
- " first matching one.
- "
- " There's yet another special case here. Consider the following:
- " If you run man -w strlen and string.3 comes up first, this is a problem. We
- " should search for a matching named one in the results list.
- " However, if you search for man -w clock_gettime, you will *only* get
- " clock_getres.2, which is the right page. Searching the resuls for
- " clock_gettime will no longer work. In this case, we should just use the
- " first one that was found in the correct section.
- "
- " Finally, we can avoid relying on -S or -s here since they are very
- " inconsistently supported. Instead, call -w with a section and a name.
- if empty(a:sect)
- let results = split(s:system(['man', s:find_arg, a:name]))
- else
- let results = split(s:system(['man', s:find_arg, a:sect, a:name]))
- endif
-
- if empty(results)
- return ''
- endif
-
- " find any that match the specified name
- let namematches = filter(copy(results), 'fnamemodify(v:val, ":t") =~ a:name')
- let sectmatches = []
-
- if !empty(namematches) && !empty(a:sect)
- let sectmatches = filter(copy(namematches), 'fnamemodify(v:val, ":e") == a:sect')
- endif
-
- return substitute(get(sectmatches, 0, get(namematches, 0, results[0])), '\n\+$', '', '')
-endfunction
-
-" s:verify_exists attempts to find the path to a manpage
-" based on the passed section and name.
-"
-" 1. If the passed section is empty, b:man_default_sects is used.
-" 2. If manpage could not be found with the given sect and name,
-" then another attempt is made with b:man_default_sects.
-" 3. If it still could not be found, then we try again without a section.
-" 4. If still not found but $MANSECT is set, then we try again with $MANSECT
-" unset.
-"
-" This function is careful to avoid duplicating a search if a previous
-" step has already done it. i.e if we use b:man_default_sects in step 1,
-" then we don't do it again in step 2.
-function! s:verify_exists(sect, name) abort
- let sect = a:sect
-
- if empty(sect)
- " no section specified, so search with b:man_default_sects
- if exists('b:man_default_sects')
- let sects = split(b:man_default_sects, ',')
- for sec in sects
- try
- let res = s:get_path(sec, a:name)
- if !empty(res)
- return res
- endif
- catch /^command error (/
- endtry
- endfor
- endif
- else
- " try with specified section
- try
- let res = s:get_path(sect, a:name)
- if !empty(res)
- return res
- endif
- catch /^command error (/
- endtry
-
- " try again with b:man_default_sects
- if exists('b:man_default_sects')
- let sects = split(b:man_default_sects, ',')
- for sec in sects
- try
- let res = s:get_path(sec, a:name)
- if !empty(res)
- return res
- endif
- catch /^command error (/
- endtry
- endfor
- endif
- endif
-
- " if none of the above worked, we will try with no section
- try
- let res = s:get_path('', a:name)
- if !empty(res)
- return res
- endif
- catch /^command error (/
- endtry
-
- " if that still didn't work, we will check for $MANSECT and try again with it
- " unset
- if !empty($MANSECT)
- try
- let MANSECT = $MANSECT
- call setenv('MANSECT', v:null)
- let res = s:get_path('', a:name)
- if !empty(res)
- return res
- endif
- catch /^command error (/
- finally
- call setenv('MANSECT', MANSECT)
- endtry
- endif
-
- " finally, if that didn't work, there is no hope
- throw 'no manual entry for ' . a:name
-endfunction
-
-" Extracts the name/section from the 'path/name.sect', because sometimes the actual section is
-" more specific than what we provided to `man` (try `:Man 3 App::CLI`).
-" Also on linux, name seems to be case-insensitive. So for `:Man PRIntf`, we
-" still want the name of the buffer to be 'printf'.
-function! s:extract_sect_and_name_path(path) abort
- let tail = fnamemodify(a:path, ':t')
- if a:path =~# '\.\%([glx]z\|bz2\|lzma\|Z\)$' " valid extensions
- let tail = fnamemodify(tail, ':r')
- endif
- let sect = matchstr(tail, '\.\zs[^.]\+$')
- let name = matchstr(tail, '^.\+\ze\.')
- return [sect, name]
-endfunction
-
-function! s:find_man() abort
- let l:win = 1
- while l:win <= winnr('$')
- let l:buf = winbufnr(l:win)
- if getbufvar(l:buf, '&filetype', '') ==# 'man'
- execute l:win.'wincmd w'
- return 1
- endif
- let l:win += 1
- endwhile
- return 0
-endfunction
-
-function! s:error(msg) abort
- redraw
- echohl ErrorMsg
- echon 'man.vim: ' a:msg
- echohl None
-endfunction
-
-" see s:extract_sect_and_name_ref on why tolower(sect)
-function! man#complete(arg_lead, cmd_line, cursor_pos) abort
- let args = split(a:cmd_line)
- let cmd_offset = index(args, 'Man')
- if cmd_offset > 0
- " Prune all arguments up to :Man itself. Otherwise modifier commands like
- " :tab, :vertical, etc. would lead to a wrong length.
- let args = args[cmd_offset:]
- endif
- let l = len(args)
- if l > 3
- return
- elseif l ==# 1
- let name = ''
- let sect = ''
- elseif a:arg_lead =~# '^[^()]\+([^()]*$'
- " cursor (|) is at ':Man printf(|' or ':Man 1 printf(|'
- " The later is is allowed because of ':Man pri<TAB>'.
- " It will offer 'priclass.d(1m)' even though section is specified as 1.
- let tmp = split(a:arg_lead, '(')
- let name = tmp[0]
- let sect = tolower(get(tmp, 1, ''))
- return s:complete(sect, '', name)
- elseif args[1] !~# '^[^()]\+$'
- " cursor (|) is at ':Man 3() |' or ':Man (3|' or ':Man 3() pri|'
- " or ':Man 3() pri |'
- return
- elseif l ==# 2
- if empty(a:arg_lead)
- " cursor (|) is at ':Man 1 |'
- let name = ''
- let sect = tolower(args[1])
- else
- " cursor (|) is at ':Man pri|'
- if a:arg_lead =~# '\/'
- " if the name is a path, complete files
- " TODO(nhooyr) why does this complete the last one automatically
- return glob(a:arg_lead.'*', 0, 1)
- endif
- let name = a:arg_lead
- let sect = ''
- endif
- elseif a:arg_lead !~# '^[^()]\+$'
- " cursor (|) is at ':Man 3 printf |' or ':Man 3 (pr)i|'
- return
- else
- " cursor (|) is at ':Man 3 pri|'
- let name = a:arg_lead
- let sect = tolower(args[1])
- endif
- return s:complete(sect, sect, name)
-endfunction
-
-function! s:get_paths(sect, name, do_fallback) abort
- " callers must try-catch this, as some `man` implementations don't support `s:find_arg`
- try
- let mandirs = join(split(s:system(['man', s:find_arg]), ':\|\n'), ',')
- let paths = globpath(mandirs, 'man?/'.a:name.'*.'.a:sect.'*', 0, 1)
- try
- " Prioritize the result from verify_exists as it obeys b:man_default_sects.
- let first = s:verify_exists(a:sect, a:name)
- let paths = filter(paths, 'v:val !=# first')
- let paths = [first] + paths
- catch
- endtry
- return paths
- catch
- if !a:do_fallback
- throw v:exception
- endif
-
- " Fallback to a single path, with the page we're trying to find.
- try
- return [s:verify_exists(a:sect, a:name)]
- catch
- return []
- endtry
- endtry
-endfunction
-
-function! s:complete(sect, psect, name) abort
- let pages = s:get_paths(a:sect, a:name, v:false)
- " We remove duplicates in case the same manpage in different languages was found.
- return uniq(sort(map(pages, 's:format_candidate(v:val, a:psect)'), 'i'))
-endfunction
-
-function! s:format_candidate(path, psect) abort
- if a:path =~# '\.\%(pdf\|in\)$' " invalid extensions
- return
- endif
- let [sect, name] = s:extract_sect_and_name_path(a:path)
- if sect ==# a:psect
- return name
- elseif sect =~# a:psect.'.\+$'
- " We include the section if the user provided section is a prefix
- " of the actual section.
- return name.'('.sect.')'
- endif
-endfunction
-
-" Called when Nvim is invoked as $MANPAGER.
-function! man#init_pager() abort
- if getline(1) =~# '^\s*$'
- silent keepjumps 1delete _
- else
- keepjumps 1
- endif
- lua require("man").highlight_man_page()
- " Guess the ref from the heading (which is usually uppercase, so we cannot
- " know the correct casing, cf. `man glDrawArraysInstanced`).
- let ref = substitute(matchstr(getline(1), '^[^)]\+)'), ' ', '_', 'g')
- try
- let b:man_sect = s:extract_sect_and_name_ref(ref)[0]
- catch
- let b:man_sect = ''
- endtry
- if -1 == match(bufname('%'), 'man:\/\/') " Avoid duplicate buffers, E95.
- execute 'silent file man://'.tolower(fnameescape(ref))
- endif
-
- call s:set_options(v:true)
-endfunction
-
-function! man#goto_tag(pattern, flags, info) abort
- let [l:sect, l:name] = s:extract_sect_and_name_ref(a:pattern)
-
- let l:paths = s:get_paths(l:sect, l:name, v:true)
- let l:structured = []
-
- for l:path in l:paths
- let [l:sect, l:name] = s:extract_sect_and_name_path(l:path)
- let l:structured += [{
- \ 'name': l:name,
- \ 'title': l:name . '(' . l:sect . ')'
- \ }]
- endfor
-
- if &cscopetag
- " return only a single entry so we work well with :cstag (#11675)
- let l:structured = l:structured[:0]
- endif
-
- return map(l:structured, {
- \ _, entry -> {
- \ 'name': entry.name,
- \ 'filename': 'man://' . entry.title,
- \ 'cmd': '1'
- \ }
- \ })
-endfunction
-
-call man#init()
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/autoload/usermark.vim b/runtime/autoload/usermark.vim
new file mode 100644
index 0000000000..b1b4113d1a
--- /dev/null
+++ b/runtime/autoload/usermark.vim
@@ -0,0 +1,7 @@
+" This is used for the default userreg function.
+
+lua vim.usermark = require('vim.usermark')
+
+function! usermark#func(action, mark) abort
+ return v:lua.vim.usermark.fn(a:action, a:mark)
+endfunction
diff --git a/runtime/autoload/userreg.vim b/runtime/autoload/userreg.vim
new file mode 100644
index 0000000000..fd026a12e6
--- /dev/null
+++ b/runtime/autoload/userreg.vim
@@ -0,0 +1,7 @@
+" This is used for the default userreg function.
+
+lua vim.userreg = require('vim.userreg')
+
+function! userreg#func(action, register, content) abort
+ return v:lua.vim.userreg.fn(a:action, a:register, a:content)
+endfunction
diff --git a/runtime/colors/blue.vim b/runtime/colors/blue.vim
index 0d2f07c654..652046b561 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: Fri 02 Sep 2022 09:41:44 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']
@@ -57,7 +57,7 @@ hi ToolbarLine guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NO
hi VertSplit guifg=#008787 guibg=NONE gui=NONE cterm=NONE
hi Visual guifg=#ffffff guibg=#008787 gui=NONE cterm=NONE
hi VisualNOS guifg=#008787 guibg=#ffffff gui=NONE cterm=NONE
-hi WarningMsg guifg=#d70000 guibg=NONE gui=NONE cterm=NONE
+hi WarningMsg guifg=#d787d7 guibg=NONE gui=NONE cterm=NONE
hi WildMenu guifg=#000087 guibg=#ffd700 gui=NONE cterm=NONE
hi debugBreakpoint guifg=#00ff00 guibg=#000087 gui=reverse cterm=reverse
hi debugPC guifg=#5fffff guibg=#000087 gui=reverse cterm=reverse
@@ -120,6 +120,8 @@ hi! link Structure Type
hi! link Tag Special
hi! link Typedef Type
hi! link Terminal Normal
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi DiffAdd guifg=#ffffff guibg=#5f875f gui=NONE cterm=NONE
hi DiffChange guifg=#ffffff guibg=#5f87af gui=NONE cterm=NONE
hi DiffText guifg=#000000 guibg=#c6c6c6 gui=NONE cterm=NONE
@@ -165,7 +167,7 @@ if s:t_Co >= 256
hi VertSplit ctermfg=30 ctermbg=NONE cterm=NONE
hi Visual ctermfg=231 ctermbg=30 cterm=NONE
hi VisualNOS ctermfg=30 ctermbg=231 cterm=NONE
- hi WarningMsg ctermfg=160 ctermbg=NONE cterm=NONE
+ hi WarningMsg ctermfg=176 ctermbg=NONE cterm=NONE
hi WildMenu ctermfg=18 ctermbg=220 cterm=NONE
hi debugBreakpoint ctermfg=46 ctermbg=18 cterm=reverse
hi debugPC ctermfg=87 ctermbg=18 cterm=reverse
@@ -228,6 +230,8 @@ if s:t_Co >= 256
hi! link Tag Special
hi! link Typedef Type
hi! link Terminal Normal
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi DiffAdd ctermfg=231 ctermbg=65 cterm=NONE
hi DiffChange ctermfg=231 ctermbg=67 cterm=NONE
hi DiffText ctermfg=16 ctermbg=251 cterm=NONE
@@ -276,7 +280,7 @@ if s:t_Co >= 16
hi VertSplit ctermfg=darkcyan ctermbg=NONE cterm=NONE
hi Visual ctermfg=white ctermbg=darkcyan cterm=NONE
hi VisualNOS ctermfg=darkcyan ctermbg=white cterm=NONE
- hi WarningMsg ctermfg=red ctermbg=NONE cterm=NONE
+ hi WarningMsg ctermfg=magenta ctermbg=NONE cterm=NONE
hi WildMenu ctermfg=darkblue ctermbg=yellow cterm=NONE
hi debugBreakpoint ctermfg=green ctermbg=darkblue cterm=reverse
hi debugPC ctermfg=cyan ctermbg=darkblue cterm=reverse
@@ -339,6 +343,8 @@ if s:t_Co >= 16
hi! link Tag Special
hi! link Typedef Type
hi! link Terminal Normal
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi DiffAdd ctermfg=white ctermbg=darkgreen cterm=NONE
hi DiffChange ctermfg=white ctermbg=blue cterm=NONE
hi DiffText ctermfg=black ctermbg=grey cterm=NONE
@@ -449,6 +455,8 @@ if s:t_Co >= 8
hi! link Tag Special
hi! link Typedef Type
hi! link Terminal Normal
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi DiffAdd ctermfg=white ctermbg=darkgreen cterm=NONE
hi DiffChange ctermfg=white ctermbg=darkblue cterm=NONE
hi DiffText ctermfg=black ctermbg=grey cterm=NONE
diff --git a/runtime/colors/darkblue.vim b/runtime/colors/darkblue.vim
index b4c286af37..4ce8687415 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: Fri 02 Sep 2022 09:40:36 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']
@@ -65,6 +65,8 @@ hi! link diffCommon WarningMsg
hi! link diffBDiffer WarningMsg
hi! link lCursor Cursor
hi! link CurSearch Search
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#c0c0c0 guibg=#000040 gui=NONE cterm=NONE
hi Conceal guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi ColorColumn guifg=#c0c0c0 guibg=#8b0000 gui=NONE cterm=NONE
@@ -171,6 +173,8 @@ if s:t_Co >= 256
hi! link diffBDiffer WarningMsg
hi! link lCursor Cursor
hi! link CurSearch Search
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=252 ctermbg=17 cterm=NONE
hi Conceal ctermfg=NONE ctermbg=NONE cterm=NONE
hi ColorColumn ctermfg=252 ctermbg=88 cterm=NONE
diff --git a/runtime/colors/delek.vim b/runtime/colors/delek.vim
index bd9c5cf52d..38f21d7156 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: Sun 04 Sep 2022 09:31:26 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']
@@ -25,6 +25,8 @@ hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
hi! link ErrorMsg Error
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#000000 guibg=#ffffff gui=NONE cterm=NONE
hi EndOfBuffer guifg=#bcbcbc guibg=NONE gui=NONE cterm=NONE
hi StatusLine guifg=#ffff00 guibg=#00008b gui=bold cterm=bold
@@ -57,7 +59,7 @@ hi Error guifg=#ff0000 guibg=#ffffff gui=reverse cterm=reverse
hi WarningMsg guifg=#cd00cd guibg=#ffffff gui=NONE cterm=NONE
hi MoreMsg guifg=#000000 guibg=#ffffff gui=bold cterm=bold
hi ModeMsg guifg=#000000 guibg=#ffffff gui=bold cterm=bold
-hi Question guifg=#00cd00 guibg=NONE gui=bold cterm=bold
+hi Question guifg=#008700 guibg=NONE gui=bold cterm=bold
hi Todo guifg=#000000 guibg=#ffff00 gui=NONE cterm=NONE
hi MatchParen guifg=#ffffff guibg=#ff1493 gui=NONE cterm=NONE
hi Search guifg=#ffffff guibg=#cd00cd gui=NONE cterm=NONE
@@ -97,6 +99,8 @@ if s:t_Co >= 256
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
hi! link ErrorMsg Error
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=16 ctermbg=231 cterm=NONE
hi EndOfBuffer ctermfg=250 ctermbg=NONE cterm=NONE
hi StatusLine ctermfg=226 ctermbg=18 cterm=bold
@@ -129,7 +133,7 @@ if s:t_Co >= 256
hi WarningMsg ctermfg=164 ctermbg=231 cterm=NONE
hi MoreMsg ctermfg=16 ctermbg=231 cterm=bold
hi ModeMsg ctermfg=16 ctermbg=231 cterm=bold
- hi Question ctermfg=40 ctermbg=NONE cterm=bold
+ hi Question ctermfg=28 ctermbg=NONE cterm=bold
hi Todo ctermfg=16 ctermbg=226 cterm=NONE
hi MatchParen ctermfg=231 ctermbg=198 cterm=NONE
hi Search ctermfg=231 ctermbg=164 cterm=NONE
diff --git a/runtime/colors/desert.vim b/runtime/colors/desert.vim
index e9b8108d19..4bfdf7eabd 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: Fri 02 Sep 2022 09:39:21 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']
@@ -25,6 +25,8 @@ hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
hi! link EndOfBuffer NonText
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#ffffff guibg=#333333 gui=NONE cterm=NONE
hi StatusLine guifg=#333333 guibg=#c2bfa5 gui=NONE cterm=NONE
hi StatusLineNC guifg=#7f7f8c guibg=#c2bfa5 gui=NONE cterm=NONE
@@ -97,6 +99,8 @@ if s:t_Co >= 256
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
hi! link EndOfBuffer NonText
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=231 ctermbg=236 cterm=NONE
hi StatusLine ctermfg=236 ctermbg=144 cterm=NONE
hi StatusLineNC ctermfg=242 ctermbg=144 cterm=NONE
diff --git a/runtime/colors/elflord.vim b/runtime/colors/elflord.vim
index 4bfda2a083..a9bdac7a1d 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: Fri 02 Sep 2022 09:44:22 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
@@ -43,6 +43,8 @@ hi! link lCursor Cursor
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
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/evening.vim b/runtime/colors/evening.vim
index 7e0609e9c4..23ff8421e8 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: Sun 04 Sep 2022 09:48:34 MSK
" Generated by Colortemplate v2.2.0
@@ -13,10 +13,10 @@ 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']
+ let g:terminal_ansi_colors = ['#000000', '#cd0000', '#00cd00', '#cdcd00', '#0087ff', '#cd00cd', '#00cdcd', '#e5e5e5', '#7f7f7f', '#ff0000', '#00ff00', '#ffff00', '#5c5cff', '#ff00ff', '#00ffff', '#ffffff']
endif
hi! link VertSplit StatusLineNC
hi! link StatusLineTerm StatusLine
@@ -64,6 +64,8 @@ hi! link String Constant
hi! link Structure Type
hi! link Tag Special
hi! link Typedef Type
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#ffffff guibg=#333333 gui=NONE cterm=NONE
hi ColorColumn guifg=NONE guibg=#8b0000 gui=NONE cterm=NONE
hi CursorLine guifg=NONE guibg=#666666 gui=NONE cterm=NONE
@@ -98,7 +100,7 @@ hi ToolbarButton guifg=NONE guibg=#999999 gui=bold cterm=bold
hi ToolbarLine guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi Visual guifg=#ffffff guibg=#999999 gui=NONE cterm=NONE
hi VisualNOS guifg=NONE guibg=NONE gui=bold,underline ctermfg=NONE ctermbg=NONE cterm=bold,underline
-hi WarningMsg guifg=#8b0000 guibg=NONE gui=NONE cterm=NONE
+hi WarningMsg guifg=#ff0000 guibg=NONE gui=NONE cterm=NONE
hi WildMenu guifg=#000000 guibg=#ffff00 gui=bold cterm=bold
hi debugBreakpoint guifg=#00008b guibg=#ff0000 gui=NONE cterm=NONE
hi debugPC guifg=#00008b guibg=#0000ff gui=NONE cterm=NONE
@@ -170,6 +172,8 @@ if s:t_Co >= 256
hi! link Structure Type
hi! link Tag Special
hi! link Typedef Type
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=231 ctermbg=236 cterm=NONE
hi ColorColumn ctermfg=NONE ctermbg=88 cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=241 cterm=NONE
@@ -204,7 +208,7 @@ if s:t_Co >= 256
hi ToolbarLine ctermfg=NONE ctermbg=NONE cterm=NONE
hi Visual ctermfg=231 ctermbg=246 cterm=NONE
hi VisualNOS ctermfg=NONE ctermbg=NONE cterm=bold,underline
- hi WarningMsg ctermfg=88 ctermbg=NONE cterm=NONE
+ hi WarningMsg ctermfg=196 ctermbg=NONE cterm=NONE
hi WildMenu ctermfg=16 ctermbg=226 cterm=bold
hi debugBreakpoint ctermfg=18 ctermbg=196 cterm=NONE
hi debugPC ctermfg=18 ctermbg=21 cterm=NONE
@@ -279,6 +283,8 @@ if s:t_Co >= 16
hi! link Structure Type
hi! link Tag Special
hi! link Typedef Type
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=white ctermbg=black cterm=NONE
hi ColorColumn ctermfg=white ctermbg=darkred cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline
@@ -313,7 +319,7 @@ if s:t_Co >= 16
hi ToolbarLine ctermfg=NONE ctermbg=NONE cterm=NONE
hi Visual ctermfg=white ctermbg=darkgray cterm=NONE
hi VisualNOS ctermfg=NONE ctermbg=NONE cterm=bold,underline
- hi WarningMsg ctermfg=darkred ctermbg=NONE cterm=NONE
+ hi WarningMsg ctermfg=red ctermbg=NONE cterm=NONE
hi WildMenu ctermfg=black ctermbg=darkyellow cterm=bold
hi debugBreakpoint ctermfg=darkblue ctermbg=red cterm=NONE
hi debugPC ctermfg=darkblue ctermbg=blue cterm=NONE
@@ -494,13 +500,26 @@ endif
" Color: grey30 #4d4d4d 239 darkgray
" Color: grey40 #666666 241 darkgray
" Color: grey60 #999999 246 darkgray
-" Color: xtermblue #0087ff 33 blue
-" Color: xtermdarkblue #006faf 25 darkblue
-" Color: xtermred #ff5f5f 203 red
" Color: comment #80a0ff 111 lightblue
" Color: darkred #8b0000 88 darkred
-" Term colors: black orange seagreen yellow xtermdarkblue darkmagenta darkcyan grey
-" Term colors: grey30 xtermred green lightyellow xtermblue magenta cyan white
+" Color: x_black #000000 16 black
+" Color: x_darkred #cd0000 160 darkred
+" Color: x_darkgreen #00cd00 40 darkgreen
+" Color: x_darkyellow #cdcd00 184 darkyellow
+" Color: x_darkblue_m #0087ff 33 darkblue
+" Color: x_darkmagenta #cd00cd 164 darkmagenta
+" Color: x_darkcyan #00cdcd 44 darkcyan
+" Color: x_gray #e5e5e5 254 gray
+" Color: x_darkgray #7f7f7f 244 darkgray
+" Color: x_red #ff0000 196 red
+" Color: x_green #00ff00 46 green
+" Color: x_yellow #ffff00 226 yellow
+" Color: x_blue #5c5cff 63 blue
+" Color: x_magenta #ff00ff 201 magenta
+" Color: x_cyan #00ffff 51 cyan
+" Color: x_white #ffffff 231 white
+" Term colors: x_black x_darkred x_darkgreen x_darkyellow x_darkblue_m x_darkmagenta x_darkcyan x_gray
+" Term colors: x_darkgray x_red x_green x_yellow x_blue x_magenta x_cyan x_white
" Color: bgDiffA #5F875F 65 darkgreen
" Color: bgDiffC #5F87AF 67 blue
" Color: bgDiffD #AF5FAF 133 magenta
diff --git a/runtime/colors/habamax.vim b/runtime/colors/habamax.vim
index 169fc28021..049413beef 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: Fri 02 Sep 2022 09:45:11 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']
@@ -21,6 +21,8 @@ endif
hi! link Terminal Normal
hi! link StatuslineTerm Statusline
hi! link StatuslineTermNC StatuslineNC
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi! link javaScriptFunction Statement
hi! link javaScriptIdentifier Statement
hi! link sqlKeyword Statement
@@ -142,6 +144,8 @@ if s:t_Co >= 256
hi! link Terminal Normal
hi! link StatuslineTerm Statusline
hi! link StatuslineTermNC StatuslineNC
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi! link javaScriptFunction Statement
hi! link javaScriptIdentifier Statement
hi! link sqlKeyword Statement
diff --git a/runtime/colors/industry.vim b/runtime/colors/industry.vim
index 359600fa4a..3f6726038e 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: Sun 04 Sep 2022 09:50:04 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']
@@ -51,7 +51,7 @@ hi Underlined guifg=#87afff guibg=NONE gui=underline cterm=underline
hi Error guifg=#ffffff guibg=#ff0000 gui=NONE cterm=NONE
hi ErrorMsg guifg=#ffffff guibg=#ff0000 gui=NONE cterm=NONE
hi ModeMsg guifg=#ffffff guibg=NONE gui=bold cterm=bold
-hi WarningMsg guifg=#870000 guibg=NONE gui=bold cterm=bold
+hi WarningMsg guifg=#ff0000 guibg=NONE gui=bold cterm=bold
hi MoreMsg guifg=#5fd75f guibg=NONE gui=bold cterm=bold
hi Question guifg=#00ff00 guibg=NONE gui=bold cterm=bold
hi Todo guifg=#005fff guibg=#ffff00 gui=NONE cterm=NONE
@@ -84,6 +84,8 @@ hi! link LineNrBelow LineNr
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi DiffAdd guifg=#ffffff guibg=#5f875f gui=NONE cterm=NONE
hi DiffChange guifg=#ffffff guibg=#5f87af gui=NONE cterm=NONE
hi DiffText guifg=#000000 guibg=#c6c6c6 gui=NONE cterm=NONE
@@ -123,7 +125,7 @@ if s:t_Co >= 256
hi Error ctermfg=231 ctermbg=196 cterm=NONE
hi ErrorMsg ctermfg=231 ctermbg=196 cterm=NONE
hi ModeMsg ctermfg=231 ctermbg=NONE cterm=bold
- hi WarningMsg ctermfg=88 ctermbg=NONE cterm=bold
+ hi WarningMsg ctermfg=196 ctermbg=NONE cterm=bold
hi MoreMsg ctermfg=77 ctermbg=NONE cterm=bold
hi Question ctermfg=46 ctermbg=NONE cterm=bold
hi Todo ctermfg=27 ctermbg=226 cterm=NONE
@@ -156,6 +158,8 @@ if s:t_Co >= 256
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi DiffAdd ctermfg=231 ctermbg=65 cterm=NONE
hi DiffChange ctermfg=231 ctermbg=67 cterm=NONE
hi DiffText ctermfg=16 ctermbg=251 cterm=NONE
@@ -198,7 +202,7 @@ if s:t_Co >= 16
hi Error ctermfg=white ctermbg=red cterm=NONE
hi ErrorMsg ctermfg=white ctermbg=red cterm=NONE
hi ModeMsg ctermfg=white ctermbg=NONE cterm=bold
- hi WarningMsg ctermfg=darkred ctermbg=NONE cterm=bold
+ hi WarningMsg ctermfg=red ctermbg=NONE cterm=bold
hi MoreMsg ctermfg=darkgreen ctermbg=NONE cterm=bold
hi Question ctermfg=green ctermbg=NONE cterm=bold
hi Todo ctermfg=blue ctermbg=yellow cterm=NONE
@@ -231,6 +235,8 @@ if s:t_Co >= 16
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi DiffAdd ctermfg=white ctermbg=darkgreen cterm=NONE
hi DiffChange ctermfg=white ctermbg=blue cterm=NONE
hi DiffText ctermfg=black ctermbg=grey cterm=NONE
diff --git a/runtime/colors/koehler.vim b/runtime/colors/koehler.vim
index 04476d1ee9..f414eeb3e6 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: Fri 02 Sep 2022 09:23:56 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
@@ -49,6 +49,8 @@ hi! link lCursor Cursor
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
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/lunaperche.vim b/runtime/colors/lunaperche.vim
index d6c73eb28c..b717ca7855 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: Sat 03 Sep 2022 14:31:51 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
@@ -81,18 +81,31 @@ hi! link shOption Normal
hi! link shCommandSub Normal
hi! link shDerefPattern shQuote
hi! link shDerefOp Special
+hi! link phpStorageClass Statement
+hi! link phpStructure Statement
+hi! link phpInclude Statement
+hi! link phpDefine Statement
+hi! link phpSpecialFunction Normal
+hi! link phpParent Normal
+hi! link phpComparison Normal
+hi! link phpOperator Normal
+hi! link phpVarSelector Special
+hi! link phpMemberSelector Special
+hi! link phpDocCustomTags phpDocTags
hi! link Terminal Normal
hi! link StatuslineTerm Statusline
hi! link StatuslineTermNC StatuslineNC
hi! link LineNrAbove LineNr
hi! link LineNrBelow LineNr
+hi! link MessageWindow PMenu
+hi! link PopupNotification Todo
if &background ==# 'dark'
if (has('termguicolors') && &termguicolors) || has('gui_running')
let g:terminal_ansi_colors = ['#000000', '#af5f5f', '#5faf5f', '#af875f', '#5f87af', '#d787af', '#5fafaf', '#c6c6c6', '#767676', '#ff5f5f', '#5fd75f', '#ffd787', '#87afd7', '#ffafd7', '#5fd7d7', '#ffffff']
endif
hi Normal guifg=#c6c6c6 guibg=#000000 gui=NONE cterm=NONE
- hi Statusline guifg=#000000 guibg=#c6c6c6 gui=bold cterm=bold
- hi StatuslineNC guifg=#000000 guibg=#767676 gui=NONE cterm=NONE
+ hi Statusline guifg=#c6c6c6 guibg=#000000 gui=bold,reverse cterm=bold,reverse
+ hi StatuslineNC guifg=#767676 guibg=#000000 gui=reverse cterm=reverse
hi VertSplit guifg=#767676 guibg=#767676 gui=NONE cterm=NONE
hi TabLine guifg=#000000 guibg=#c6c6c6 gui=NONE cterm=NONE
hi TabLineFill guifg=NONE guibg=#767676 gui=NONE cterm=NONE
@@ -107,7 +120,7 @@ if &background ==# 'dark'
hi EndOfBuffer guifg=#585858 guibg=NONE gui=NONE cterm=NONE
hi SpecialKey guifg=#585858 guibg=NONE gui=NONE cterm=NONE
hi Pmenu guifg=NONE guibg=#1c1c1c gui=NONE cterm=NONE
- hi PmenuSel guifg=NONE guibg=#005f00 gui=NONE cterm=NONE
+ hi PmenuSel guifg=NONE guibg=#444444 gui=NONE cterm=NONE
hi PmenuThumb guifg=NONE guibg=#c6c6c6 gui=NONE cterm=NONE
hi PmenuSbar guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi SignColumn guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
@@ -169,7 +182,6 @@ if &background ==# 'dark'
hi dirFilterMenuBookmarkPath guifg=#878787 guibg=NONE gui=NONE cterm=NONE
hi dirFilterMenuHistoryPath guifg=#878787 guibg=NONE gui=NONE cterm=NONE
hi FilterMenuLineNr guifg=#878787 guibg=NONE gui=NONE cterm=NONE
- hi CocMenuSel guifg=NONE guibg=#005f00 gui=NONE cterm=NONE
hi CocSearch guifg=#ffd787 guibg=NONE gui=NONE cterm=NONE
else
" Light background
@@ -193,7 +205,7 @@ else
hi EndOfBuffer guifg=#9e9e9e guibg=NONE gui=NONE cterm=NONE
hi SpecialKey guifg=#9e9e9e guibg=NONE gui=NONE cterm=NONE
hi Pmenu guifg=NONE guibg=#eeeeee gui=NONE cterm=NONE
- hi PmenuSel guifg=NONE guibg=#afd7af gui=NONE cterm=NONE
+ hi PmenuSel guifg=NONE guibg=#c6c6c6 gui=NONE cterm=NONE
hi PmenuThumb guifg=NONE guibg=#767676 gui=NONE cterm=NONE
hi PmenuSbar guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi SignColumn guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
@@ -256,7 +268,6 @@ else
hi dirFilterMenuHistoryPath guifg=#626262 guibg=NONE gui=NONE cterm=NONE
hi FilterMenuDirectorySubtle guifg=#626262 guibg=NONE gui=NONE cterm=NONE
hi FilterMenuLineNr guifg=#626262 guibg=NONE gui=NONE cterm=NONE
- hi CocMenuSel guifg=NONE guibg=#afd7af gui=NONE cterm=NONE
hi CocSearch guifg=#870000 guibg=NONE gui=NONE cterm=NONE
endif
@@ -329,15 +340,28 @@ if s:t_Co >= 256
hi! link shCommandSub Normal
hi! link shDerefPattern shQuote
hi! link shDerefOp Special
+ hi! link phpStorageClass Statement
+ hi! link phpStructure Statement
+ hi! link phpInclude Statement
+ hi! link phpDefine Statement
+ hi! link phpSpecialFunction Normal
+ hi! link phpParent Normal
+ hi! link phpComparison Normal
+ hi! link phpOperator Normal
+ hi! link phpVarSelector Special
+ hi! link phpMemberSelector Special
+ hi! link phpDocCustomTags phpDocTags
hi! link Terminal Normal
hi! link StatuslineTerm Statusline
hi! link StatuslineTermNC StatuslineNC
hi! link LineNrAbove LineNr
hi! link LineNrBelow LineNr
+ hi! link MessageWindow PMenu
+ hi! link PopupNotification Todo
if &background ==# 'dark'
hi Normal ctermfg=251 ctermbg=16 cterm=NONE
- hi Statusline ctermfg=16 ctermbg=251 cterm=bold
- hi StatuslineNC ctermfg=16 ctermbg=243 cterm=NONE
+ hi Statusline ctermfg=251 ctermbg=16 cterm=bold,reverse
+ hi StatuslineNC ctermfg=243 ctermbg=16 cterm=reverse
hi VertSplit ctermfg=243 ctermbg=243 cterm=NONE
hi TabLine ctermfg=16 ctermbg=251 cterm=NONE
hi TabLineFill ctermfg=NONE ctermbg=243 cterm=NONE
@@ -352,7 +376,7 @@ if s:t_Co >= 256
hi EndOfBuffer ctermfg=240 ctermbg=NONE cterm=NONE
hi SpecialKey ctermfg=240 ctermbg=NONE cterm=NONE
hi Pmenu ctermfg=NONE ctermbg=234 cterm=NONE
- hi PmenuSel ctermfg=NONE ctermbg=22 cterm=NONE
+ hi PmenuSel ctermfg=NONE ctermbg=238 cterm=NONE
hi PmenuThumb ctermfg=NONE ctermbg=251 cterm=NONE
hi PmenuSbar ctermfg=NONE ctermbg=NONE cterm=NONE
hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE
@@ -412,7 +436,6 @@ if s:t_Co >= 256
hi dirFilterMenuBookmarkPath ctermfg=102 ctermbg=NONE cterm=NONE
hi dirFilterMenuHistoryPath ctermfg=102 ctermbg=NONE cterm=NONE
hi FilterMenuLineNr ctermfg=102 ctermbg=NONE cterm=NONE
- hi CocMenuSel ctermfg=NONE ctermbg=22 cterm=NONE
hi CocSearch ctermfg=222 ctermbg=NONE cterm=NONE
else
" Light background
@@ -433,7 +456,7 @@ if s:t_Co >= 256
hi EndOfBuffer ctermfg=247 ctermbg=NONE cterm=NONE
hi SpecialKey ctermfg=247 ctermbg=NONE cterm=NONE
hi Pmenu ctermfg=NONE ctermbg=255 cterm=NONE
- hi PmenuSel ctermfg=NONE ctermbg=151 cterm=NONE
+ hi PmenuSel ctermfg=NONE ctermbg=251 cterm=NONE
hi PmenuThumb ctermfg=NONE ctermbg=243 cterm=NONE
hi PmenuSbar ctermfg=NONE ctermbg=NONE cterm=NONE
hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE
@@ -494,7 +517,6 @@ if s:t_Co >= 256
hi dirFilterMenuHistoryPath ctermfg=241 ctermbg=NONE cterm=NONE
hi FilterMenuDirectorySubtle ctermfg=241 ctermbg=NONE cterm=NONE
hi FilterMenuLineNr ctermfg=241 ctermbg=NONE cterm=NONE
- hi CocMenuSel ctermfg=NONE ctermbg=151 cterm=NONE
hi CocSearch ctermfg=88 ctermbg=NONE cterm=NONE
endif
unlet s:t_Co
@@ -504,8 +526,8 @@ endif
if s:t_Co >= 16
if &background ==# 'dark'
hi Normal ctermfg=grey ctermbg=black cterm=NONE
- hi Statusline ctermfg=black ctermbg=grey cterm=bold
- hi StatuslineNC ctermfg=black ctermbg=darkgrey cterm=NONE
+ hi Statusline ctermfg=grey ctermbg=black cterm=bold,reverse
+ hi StatuslineNC ctermfg=darkgrey ctermbg=black cterm=reverse
hi VertSplit ctermfg=darkgrey ctermbg=darkgrey cterm=NONE
hi TabLine ctermfg=black ctermbg=grey cterm=NONE
hi TabLineFill ctermfg=NONE ctermbg=darkgrey cterm=NONE
@@ -520,7 +542,7 @@ if s:t_Co >= 16
hi EndOfBuffer ctermfg=grey ctermbg=NONE cterm=NONE
hi SpecialKey ctermfg=grey ctermbg=NONE cterm=NONE
hi Pmenu ctermfg=black ctermbg=darkgrey cterm=NONE
- hi PmenuSel ctermfg=black ctermbg=darkgreen cterm=NONE
+ hi PmenuSel ctermfg=black ctermbg=darkcyan cterm=NONE
hi PmenuThumb ctermfg=NONE ctermbg=grey cterm=NONE
hi PmenuSbar ctermfg=NONE ctermbg=NONE cterm=NONE
hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE
@@ -567,6 +589,20 @@ if s:t_Co >= 16
hi diffAdded ctermfg=green ctermbg=NONE cterm=NONE
hi diffRemoved ctermfg=darkred ctermbg=NONE cterm=NONE
hi diffSubname ctermfg=magenta ctermbg=NONE cterm=NONE
+ hi dirType ctermfg=darkmagenta ctermbg=NONE cterm=NONE
+ hi dirPermissionUser ctermfg=darkgreen ctermbg=NONE cterm=NONE
+ hi dirPermissionGroup ctermfg=darkyellow ctermbg=NONE cterm=NONE
+ hi dirPermissionOther ctermfg=darkcyan ctermbg=NONE cterm=NONE
+ hi dirOwner ctermfg=darkgrey ctermbg=NONE cterm=NONE
+ hi dirGroup ctermfg=darkgrey ctermbg=NONE cterm=NONE
+ hi dirTime ctermfg=darkgrey ctermbg=NONE cterm=NONE
+ hi dirSize ctermfg=yellow ctermbg=NONE cterm=NONE
+ hi dirSizeMod ctermfg=darkmagenta ctermbg=NONE cterm=NONE
+ hi FilterMenuDirectorySubtle ctermfg=grey ctermbg=NONE cterm=NONE
+ hi dirFilterMenuBookmarkPath ctermfg=grey ctermbg=NONE cterm=NONE
+ hi dirFilterMenuHistoryPath ctermfg=grey ctermbg=NONE cterm=NONE
+ hi FilterMenuLineNr ctermfg=grey ctermbg=NONE cterm=NONE
+ hi CocSearch ctermfg=yellow ctermbg=NONE cterm=NONE
else
" Light background
hi Normal ctermfg=black ctermbg=white cterm=NONE
@@ -586,7 +622,7 @@ if s:t_Co >= 16
hi EndOfBuffer ctermfg=darkgrey ctermbg=NONE cterm=NONE
hi SpecialKey ctermfg=darkgrey ctermbg=NONE cterm=NONE
hi Pmenu ctermfg=black ctermbg=grey cterm=NONE
- hi PmenuSel ctermfg=black ctermbg=darkgreen cterm=NONE
+ hi PmenuSel ctermfg=black ctermbg=darkcyan cterm=NONE
hi PmenuThumb ctermfg=NONE ctermbg=darkgrey cterm=NONE
hi PmenuSbar ctermfg=NONE ctermbg=NONE cterm=NONE
hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE
@@ -633,6 +669,21 @@ if s:t_Co >= 16
hi diffAdded ctermfg=darkgreen ctermbg=NONE cterm=NONE
hi diffRemoved ctermfg=red ctermbg=NONE cterm=NONE
hi diffSubname ctermfg=darkmagenta ctermbg=NONE cterm=NONE
+ hi dirType ctermfg=darkcyan ctermbg=NONE cterm=NONE
+ hi dirPermissionUser ctermfg=darkyellow ctermbg=NONE cterm=NONE
+ hi dirPermissionGroup ctermfg=darkgreen ctermbg=NONE cterm=NONE
+ hi dirPermissionOther ctermfg=darkmagenta ctermbg=NONE cterm=NONE
+ hi dirOwner ctermfg=grey ctermbg=NONE cterm=NONE
+ hi dirGroup ctermfg=grey ctermbg=NONE cterm=NONE
+ hi dirTime ctermfg=grey ctermbg=NONE cterm=NONE
+ hi dirSize ctermfg=darkred ctermbg=NONE cterm=NONE
+ hi dirSizeMod ctermfg=darkcyan ctermbg=NONE cterm=NONE
+ hi dirLink ctermfg=darkgreen ctermbg=NONE cterm=bold
+ hi dirFilterMenuBookmarkPath ctermfg=darkgrey ctermbg=NONE cterm=NONE
+ hi dirFilterMenuHistoryPath ctermfg=darkgrey ctermbg=NONE cterm=NONE
+ hi FilterMenuDirectorySubtle ctermfg=darkgrey ctermbg=NONE cterm=NONE
+ hi FilterMenuLineNr ctermfg=darkgrey ctermbg=NONE cterm=NONE
+ hi CocSearch ctermfg=darkred ctermbg=NONE cterm=NONE
endif
unlet s:t_Co
finish
@@ -659,7 +710,7 @@ if s:t_Co >= 8
hi Pmenu ctermfg=black ctermbg=grey cterm=NONE
hi PmenuThumb ctermfg=NONE ctermbg=darkgreen cterm=NONE
hi PmenuSbar ctermfg=NONE ctermbg=NONE cterm=NONE
- hi PmenuSel ctermfg=black ctermbg=darkgreen cterm=NONE
+ hi PmenuSel ctermfg=black ctermbg=darkcyan cterm=NONE
hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE
hi Error ctermfg=grey ctermbg=darkred cterm=NONE
hi ErrorMsg ctermfg=grey ctermbg=darkred cterm=NONE
@@ -688,7 +739,7 @@ if s:t_Co >= 8
hi Comment ctermfg=darkblue ctermbg=NONE cterm=NONE
hi Constant ctermfg=darkred ctermbg=NONE cterm=NONE
hi Identifier ctermfg=NONE ctermbg=NONE cterm=NONE
- hi Statement ctermfg=black ctermbg=NONE cterm=bold
+ hi Statement ctermfg=grey ctermbg=NONE cterm=bold
hi Type ctermfg=darkgreen ctermbg=NONE cterm=bold
hi PreProc ctermfg=darkyellow ctermbg=NONE cterm=NONE
hi Special ctermfg=darkcyan ctermbg=NONE cterm=NONE
@@ -722,7 +773,7 @@ if s:t_Co >= 8
hi Pmenu ctermfg=grey ctermbg=black cterm=NONE
hi PmenuThumb ctermfg=NONE ctermbg=darkgreen cterm=NONE
hi PmenuSbar ctermfg=NONE ctermbg=NONE cterm=NONE
- hi PmenuSel ctermfg=black ctermbg=darkgreen cterm=NONE
+ hi PmenuSel ctermfg=black ctermbg=darkcyan cterm=NONE
hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE
hi Error ctermfg=grey ctermbg=darkred cterm=NONE
hi ErrorMsg ctermfg=grey ctermbg=darkred cterm=NONE
@@ -864,7 +915,7 @@ endif
" Color: colorlC #FF5FFF 207 magenta
" Color: colorV #005F87 24 darkblue
" Color: colorMP #C5E7C5 30 darkcyan
-" Color: colorPMenuSel #005F00 22 darkgreen
+" Color: colorPMenuSel #444444 238 darkcyan
" Color: colorDim #878787 102 grey
" Color: diffAdd #AF87AF 139 darkmagenta
" Color: diffDelete #D78787 174 darkred
@@ -898,7 +949,7 @@ endif
" Color: colorlC #FF00FF 201 magenta
" Color: colorV #5F87AF 67 darkblue
" Color: colorMP #C5E7C5 30 darkcyan
-" Color: colorPMenuSel #AFD7AF 151 darkgreen
+" Color: colorPMenuSel #C6C6C6 251 darkcyan
" Color: colorDim #626262 241 darkgrey
" Color: diffAdd #D7AFD7 182 darkmagenta
" Color: diffDelete #870000 88 darkred
diff --git a/runtime/colors/morning.vim b/runtime/colors/morning.vim
index 5764d0df78..a7aec49808 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: Fri 02 Sep 2022 09:46:24 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']
@@ -26,6 +26,8 @@ hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
hi! link StatuslineTerm Statusline
hi! link StatuslineTermNC StatuslineNC
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#000000 guibg=#e4e4e4 gui=NONE cterm=NONE
hi EndOfBuffer guifg=#0000ff guibg=#cccccc gui=bold cterm=bold
hi Folded guifg=#00008b guibg=#d3d3d3 gui=NONE cterm=NONE
@@ -96,6 +98,8 @@ if s:t_Co >= 256
hi! link CursorLineSign CursorLine
hi! link StatuslineTerm Statusline
hi! link StatuslineTermNC StatuslineNC
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=16 ctermbg=254 cterm=NONE
hi EndOfBuffer ctermfg=21 ctermbg=252 cterm=bold
hi Folded ctermfg=18 ctermbg=252 cterm=NONE
diff --git a/runtime/colors/murphy.vim b/runtime/colors/murphy.vim
index b7cf6ce985..60a6aed428 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: Fri 02 Sep 2022 09:47:20 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']
@@ -26,6 +26,8 @@ hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
hi! link StatusLineTerm StatusLine
hi! link StatusLineTermNC StatusLineNC
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#87ff87 guibg=#000000 gui=NONE cterm=NONE
hi EndOfBuffer guifg=#0000ff guibg=#000000 gui=NONE cterm=NONE
hi StatusLine guifg=#ffffff guibg=#00008b gui=NONE cterm=NONE
@@ -96,6 +98,8 @@ if s:t_Co >= 256
hi! link CursorLineSign CursorLine
hi! link StatusLineTerm StatusLine
hi! link StatusLineTermNC StatusLineNC
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=120 ctermbg=16 cterm=NONE
hi EndOfBuffer ctermfg=21 ctermbg=16 cterm=NONE
hi StatusLine ctermfg=231 ctermbg=18 cterm=NONE
diff --git a/runtime/colors/pablo.vim b/runtime/colors/pablo.vim
index 521ea44aaf..f404951b2a 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: Sun 04 Sep 2022 09:53:40 MSK
" Generated by Colortemplate v2.2.0
@@ -12,18 +12,20 @@ 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']
endif
-hi Normal guifg=#ffffff guibg=#000000 gui=NONE cterm=NONE
hi! link Terminal Normal
hi! link StatusLineTerm StatusLine
hi! link StatusLineTermNC StatusLineNC
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
+hi Normal guifg=#ffffff guibg=#000000 gui=NONE cterm=NONE
hi Comment guifg=#808080 guibg=NONE gui=NONE cterm=NONE
hi Constant guifg=#00ffff guibg=NONE gui=NONE cterm=NONE
hi Identifier guifg=#00c0c0 guibg=NONE gui=NONE cterm=NONE
@@ -88,13 +90,15 @@ hi DiffText guifg=#000000 guibg=#c6c6c6 gui=NONE cterm=NONE
hi DiffDelete guifg=#ffffff guibg=#af5faf gui=NONE cterm=NONE
if s:t_Co >= 256
- hi Normal ctermfg=231 ctermbg=16 cterm=NONE
hi! link Terminal Normal
hi! link StatusLineTerm StatusLine
hi! link StatusLineTermNC StatusLineNC
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
+ hi Normal ctermfg=231 ctermbg=16 cterm=NONE
hi Comment ctermfg=244 ctermbg=NONE cterm=NONE
hi Constant ctermfg=51 ctermbg=NONE cterm=NONE
hi Identifier ctermfg=37 ctermbg=NONE cterm=NONE
@@ -117,7 +121,7 @@ if s:t_Co >= 256
hi NonText ctermfg=63 ctermbg=NONE cterm=bold
hi EndOfBuffer ctermfg=63 ctermbg=NONE cterm=bold
hi ErrorMsg ctermfg=231 ctermbg=160 cterm=NONE
- hi WarningMsg ctermfg=224 ctermbg=NONE cterm=NONE
+ hi WarningMsg ctermfg=196 ctermbg=NONE cterm=NONE
hi SignColumn ctermfg=51 ctermbg=248 cterm=NONE
hi ColorColumn ctermfg=NONE ctermbg=239 cterm=NONE
hi FoldColumn ctermfg=102 ctermbg=236 cterm=NONE
@@ -163,12 +167,6 @@ endif
if s:t_Co >= 16
hi Normal ctermfg=white ctermbg=black cterm=NONE
- hi! link Terminal Normal
- hi! link StatusLineTerm StatusLine
- hi! link StatusLineTermNC StatusLineNC
- hi! link CurSearch Search
- hi! link CursorLineFold CursorLine
- hi! link CursorLineSign CursorLine
hi Comment ctermfg=darkgrey ctermbg=NONE cterm=NONE
hi Constant ctermfg=cyan ctermbg=NONE cterm=NONE
hi Identifier ctermfg=darkcyan ctermbg=NONE cterm=NONE
@@ -191,7 +189,7 @@ if s:t_Co >= 16
hi NonText ctermfg=blue ctermbg=NONE cterm=bold
hi EndOfBuffer ctermfg=blue ctermbg=NONE cterm=bold
hi ErrorMsg ctermfg=white ctermbg=darkred cterm=NONE
- hi WarningMsg ctermfg=darkred ctermbg=NONE cterm=NONE
+ hi WarningMsg ctermfg=red ctermbg=NONE cterm=NONE
hi SignColumn ctermfg=cyan ctermbg=black cterm=NONE
hi ColorColumn ctermfg=white ctermbg=darkgrey cterm=NONE
hi FoldColumn ctermfg=NONE ctermbg=NONE cterm=NONE
@@ -405,7 +403,7 @@ endif
" Color: SpecialKey #00ffff 81 cyan
" Color: StatusLineTerm #90ee90 121 darkgreen
" Color: Title #ff00ff 225 magenta
-" Color: WarningMsg #ff0000 224 darkred
+" Color: WarningMsg #ff0000 196 red
" Color: ToolbarLine #7f7f7f 242 darkgrey
" Color: ToolbarButton #d3d3d3 254 grey
" Color: Underlined #80a0ff 111 darkgreen
diff --git a/runtime/colors/peachpuff.vim b/runtime/colors/peachpuff.vim
index 3e896ffdeb..130eceeb18 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: Fri 02 Sep 2022 09:50:02 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']
@@ -24,6 +24,8 @@ hi! link LineNrBelow LineNr
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#000000 guibg=#ffdab9 gui=NONE cterm=NONE
hi Folded guifg=#000000 guibg=#e3c1a5 gui=NONE cterm=NONE
hi CursorLine guifg=NONE guibg=#f5c195 gui=NONE cterm=NONE
@@ -94,6 +96,8 @@ if s:t_Co >= 256
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=16 ctermbg=223 cterm=NONE
hi Folded ctermfg=16 ctermbg=252 cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=180 cterm=NONE
diff --git a/runtime/colors/quiet.vim b/runtime/colors/quiet.vim
index 4c4baa994c..9e81ba3857 100644
--- a/runtime/colors/quiet.vim
+++ b/runtime/colors/quiet.vim
@@ -4,18 +4,20 @@
" 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: Fri 02 Sep 2022 09:55:30 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
hi! link StatusLineTermNC StatusLineNC
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi! link Boolean Constant
hi! link Character Constant
hi! link Conditional Statement
diff --git a/runtime/colors/ron.vim b/runtime/colors/ron.vim
index a529d6c199..ea37b646a6 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: Fri 02 Sep 2022 09:50:56 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
@@ -46,6 +46,8 @@ hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
hi! link LineNrAbove LineNr
hi! link LineNrBelow LineNr
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
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/shine.vim b/runtime/colors/shine.vim
index b84be280e1..f9b1e39324 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: Fri 02 Sep 2022 09:51:42 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']
@@ -28,6 +28,8 @@ hi! link EndOfBuffer NonText
hi! link ErrorMsg Error
hi! link Tag Special
hi! link Operator Statement
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#000000 guibg=#ffffff gui=NONE cterm=NONE
hi Folded guifg=#00008b guibg=#dadada gui=NONE cterm=NONE
hi CursorLine guifg=NONE guibg=#dadada gui=NONE cterm=NONE
@@ -104,6 +106,8 @@ if s:t_Co >= 256
hi! link ErrorMsg Error
hi! link Tag Special
hi! link Operator Statement
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=16 ctermbg=231 cterm=NONE
hi Folded ctermfg=18 ctermbg=253 cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=253 cterm=NONE
diff --git a/runtime/colors/slate.vim b/runtime/colors/slate.vim
index 49dbc6387c..04fbc6d6c8 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: Fri 02 Sep 2022 09:52:25 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']
@@ -24,6 +24,8 @@ hi! link LineNrBelow LineNr
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#ffffff guibg=#262626 gui=NONE cterm=NONE
hi EndOfBuffer guifg=#5f87d7 guibg=NONE gui=NONE cterm=NONE
hi StatusLine guifg=#000000 guibg=#afaf87 gui=NONE cterm=NONE
@@ -99,6 +101,8 @@ if s:t_Co >= 256
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=231 ctermbg=235 cterm=NONE
hi EndOfBuffer ctermfg=68 ctermbg=NONE cterm=NONE
hi StatusLine ctermfg=16 ctermbg=144 cterm=NONE
diff --git a/runtime/colors/torte.vim b/runtime/colors/torte.vim
index ce36507ae8..01d5f0b4e0 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: Fri 02 Sep 2022 09:53:21 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']
@@ -26,6 +26,8 @@ hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
hi! link StatusLineTerm StatusLine
hi! link StatusLineTermNC StatusLineNC
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#cccccc guibg=#000000 gui=NONE cterm=NONE
hi Comment guifg=#80a0ff guibg=NONE gui=NONE cterm=NONE
hi Constant guifg=#ffa0a0 guibg=NONE gui=NONE cterm=NONE
@@ -97,6 +99,8 @@ if s:t_Co >= 256
hi! link CursorLineSign CursorLine
hi! link StatusLineTerm StatusLine
hi! link StatusLineTermNC StatusLineNC
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=251 ctermbg=16 cterm=NONE
hi Comment ctermfg=111 ctermbg=NONE cterm=NONE
hi Constant ctermfg=217 ctermbg=NONE cterm=NONE
diff --git a/runtime/colors/zellner.vim b/runtime/colors/zellner.vim
index 135591052c..ab794c0193 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: Fri 02 Sep 2022 09:54:15 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']
@@ -24,6 +24,8 @@ hi! link LineNrBelow LineNr
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+hi! link MessageWindow Pmenu
+hi! link PopupNotification Todo
hi Normal guifg=#000000 guibg=#ffffff gui=NONE cterm=NONE
hi Folded guifg=#00008b guibg=#d3d3d3 gui=NONE cterm=NONE
hi CursorLine guifg=NONE guibg=#e5e5e5 gui=NONE cterm=NONE
@@ -95,6 +97,8 @@ if s:t_Co >= 256
hi! link CurSearch Search
hi! link CursorLineFold CursorLine
hi! link CursorLineSign CursorLine
+ hi! link MessageWindow Pmenu
+ hi! link PopupNotification Todo
hi Normal ctermfg=16 ctermbg=231 cterm=NONE
hi Folded ctermfg=18 ctermbg=252 cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=254 cterm=NONE
diff --git a/runtime/compiler/raco.vim b/runtime/compiler/raco.vim
new file mode 100644
index 0000000000..bd10859aa9
--- /dev/null
+++ b/runtime/compiler/raco.vim
@@ -0,0 +1,14 @@
+" Vim compiler file
+" Compiler: raco (Racket command-line tools)
+" Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com>
+" URL: https://github.com/benknoble/vim-racket
+" Last Change: 2022 Aug 12
+
+let current_compiler = 'raco'
+
+if exists(":CompilerSet") != 2
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+CompilerSet makeprg=raco
+CompilerSet errorformat=%f:%l:%c:%m
diff --git a/runtime/compiler/racomake.vim b/runtime/compiler/racomake.vim
new file mode 100644
index 0000000000..dae95fec42
--- /dev/null
+++ b/runtime/compiler/racomake.vim
@@ -0,0 +1,14 @@
+" Vim compiler file
+" Compiler: raco make (Racket command-line tools)
+" Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com>
+" URL: https://github.com/benknoble/vim-racket
+" Last Change: 2022 Aug 12
+
+let current_compiler = 'racomake'
+
+if exists(":CompilerSet") != 2
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+CompilerSet makeprg=raco\ make\ --\ %
+CompilerSet errorformat=%f:%l:%c:%m
diff --git a/runtime/compiler/racosetup.vim b/runtime/compiler/racosetup.vim
new file mode 100644
index 0000000000..1efe8a15a2
--- /dev/null
+++ b/runtime/compiler/racosetup.vim
@@ -0,0 +1,14 @@
+" Vim compiler file
+" Compiler: raco setup (Racket command-line tools)
+" Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com>
+" URL: https://github.com/benknoble/vim-racket
+" Last Change: 2022 Aug 12
+
+let current_compiler = 'racosetup'
+
+if exists(":CompilerSet") != 2
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+CompilerSet makeprg=raco\ setup
+CompilerSet errorformat=%f:%l:%c:%m
diff --git a/runtime/compiler/racotest.vim b/runtime/compiler/racotest.vim
new file mode 100644
index 0000000000..d2a1a3c0f3
--- /dev/null
+++ b/runtime/compiler/racotest.vim
@@ -0,0 +1,14 @@
+" Vim compiler file
+" Compiler: raco test (Racket command-line tools)
+" Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com>
+" URL: https://github.com/benknoble/vim-racket
+" Last Change: 2022 Aug 12
+
+let current_compiler = 'racotest'
+
+if exists(":CompilerSet") != 2
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+CompilerSet makeprg=raco\ test\ %
+CompilerSet errorformat=location:%f:%l:%c
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index a388592981..00a3759936 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.
@@ -1067,9 +1067,11 @@ nvim_input_mouse({button}, {action}, {modifier}, {grid}, {row}, {col})
|api-fast|
Parameters: ~
- {button} Mouse button: one of "left", "right", "middle", "wheel".
+ {button} Mouse button: one of "left", "right", "middle", "wheel",
+ "move".
{action} For ordinary buttons, one of "press", "drag", "release".
For the wheel, one of "up", "down", "left", "right".
+ Ignored for "move".
{modifier} String of modifiers each represented by a single char. The
same specifiers are used as for a key press, except that
the "-" separator is optional, so "C-A-", "c-a" and "CA"
@@ -1839,13 +1841,14 @@ nvim_parse_cmd({str}, {opts}) *nvim_parse_cmd()*
• browse: (boolean) |:browse|.
• confirm: (boolean) |:confirm|.
• hide: (boolean) |:hide|.
+ • horizontal: (boolean) |:horizontal|.
• keepalt: (boolean) |:keepalt|.
• keepjumps: (boolean) |:keepjumps|.
• keepmarks: (boolean) |:keepmarks|.
• keeppatterns: (boolean) |:keeppatterns|.
• lockmarks: (boolean) |:lockmarks|.
• noswapfile: (boolean) |:noswapfile|.
- • tab: (integer) |:tab|.
+ • tab: (integer) |:tab|. -1 when omitted.
• verbose: (integer) |:verbose|. -1 when omitted.
• vertical: (boolean) |:vertical|.
• split: (string) Split modifier string, is an empty string when
@@ -2643,6 +2646,8 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
When a character is supplied it is used as |:syn-cchar|.
"hl_group" is used as highlight for the cchar if provided,
otherwise it defaults to |hl-Conceal|.
+ • spell: boolean indicating that spell checking should be
+ performed within this extmark
• ui_watched: boolean that indicates the mark should be
drawn by a UI. When set, the UI will receive win_extmark
events. Note: the mark is positioned by virt_text
@@ -2674,7 +2679,7 @@ nvim_get_namespaces() *nvim_get_namespaces()*
dict that maps from names to namespace ids.
*nvim_set_decoration_provider()*
-nvim_set_decoration_provider({ns_id}, {opts})
+nvim_set_decoration_provider({ns_id}, {*opts})
Set or change decoration provider for a namespace
This is a very general purpose interface for having lua callbacks being
@@ -2706,7 +2711,7 @@ nvim_set_decoration_provider({ns_id}, {opts})
Parameters: ~
{ns_id} Namespace id from |nvim_create_namespace()|
- {opts} Callbacks invoked during redraw:
+ {opts} Table of callbacks:
• on_start: called first on each screen redraw ["start",
tick]
• on_buf: called for each buffer being redrawn (before window
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 63226fe701..7a2c540ea2 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -412,6 +412,8 @@ CmdwinLeave Before leaving the command-line window.
|cmdwin-char|
*ColorScheme*
ColorScheme After loading a color scheme. |:colorscheme|
+ Not triggered if the color scheme is not
+ found.
The pattern is matched against the
colorscheme name. <afile> can be used for the
name of the actual file where this option was
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 0be9e9b9d1..c70643d12c 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -6,9 +6,7 @@
Builtin functions *builtin-functions*
-1. Overview |builtin-function-list|
-2. Details |builtin-function-details|
-3. Matching a pattern in a String |string-match|
+ Type |gO| to see the table of contents.
==============================================================================
1. Overview *builtin-function-list*
@@ -400,6 +398,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
@@ -527,6 +526,8 @@ uniq({list} [, {func} [, {dict}]])
List remove adjacent duplicates from a list
values({dict}) List values in {dict}
virtcol({expr}) Number screen column of cursor or mark
+virtcol2col({winid}, {lnum}, {col})
+ Number byte index of a character on screen
visualmode([expr]) String last visual mode used
wait({timeout}, {condition} [, {interval}])
Number Wait until {condition} is satisfied
@@ -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
@@ -1270,7 +1276,7 @@ complete_info([{what}]) *complete_info()*
typed text only, or the last completion after
no item is selected when using the <Up> or
<Down> keys)
- inserted Inserted string. [NOT IMPLEMENT YET]
+ inserted Inserted string. [NOT IMPLEMENTED YET]
*complete_info_mode*
mode values are:
@@ -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.
@@ -2496,10 +2507,11 @@ funcref({name} [, {arglist}] [, {dict}])
Can also be used as a |method|: >
GetFuncname()->funcref([arg])
<
- *function()* *E700* *E922* *E923*
+ *function()* *partial* *E700* *E922* *E923*
function({name} [, {arglist}] [, {dict}])
Return a |Funcref| variable that refers to function {name}.
- {name} can be a user defined function or an internal function.
+ {name} can be the name of a user defined function or an
+ internal function.
{name} can also be a Funcref or a partial. When it is a
partial the dict stored in it will be used and the {dict}
@@ -2518,30 +2530,56 @@ function({name} [, {arglist}] [, {dict}])
The arguments are passed to the function in front of other
arguments, but after any argument from |method|. Example: >
func Callback(arg1, arg2, name)
- ...
+ "...
let Partial = function('Callback', ['one', 'two'])
- ...
+ "...
call Partial('name')
< Invokes the function as with: >
call Callback('one', 'two', 'name')
+< With a |method|: >
+ func Callback(one, two, three)
+ "...
+ let Partial = function('Callback', ['two'])
+ "...
+ eval 'one'->Partial('three')
+< Invokes the function as with: >
+ call Callback('one', 'two', 'three')
+
+< The function() call can be nested to add more arguments to the
+ Funcref. The extra arguments are appended to the list of
+ arguments. Example: >
+ func Callback(arg1, arg2, name)
+ "...
+ let Func = function('Callback', ['one'])
+ let Func2 = function(Func, ['two'])
+ "...
+ call Func2('name')
+< Invokes the function as with: >
+ call Callback('one', 'two', 'name')
+
< The Dictionary is only useful when calling a "dict" function.
In that case the {dict} is passed in as "self". Example: >
function Callback() dict
echo "called for " .. self.name
endfunction
- ...
+ "...
let context = {"name": "example"}
let Func = function('Callback', context)
- ...
+ "...
call Func() " will echo: called for example
+< The use of function() is not needed when there are no extra
+ arguments, these two are equivalent, if Callback() is defined
+ as context.Callback(): >
+ let Func = function('Callback', context)
+ let Func = context.Callback
< The argument list and the Dictionary can be combined: >
function Callback(arg1, count) dict
- ...
+ "...
let context = {"name": "example"}
let Func = function('Callback', ['one'], context)
- ...
+ "...
call Func(500)
< Invokes the function as with: >
call context.Callback('one', 500)
@@ -2870,7 +2908,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 +2918,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 +2929,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 +2939,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 +5005,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.
@@ -5580,12 +5622,19 @@ nvim_...({...}) *E5555* *nvim_...()* *eval-api*
or({expr}, {expr}) *or()*
Bitwise OR on the two arguments. The arguments are converted
to a number. A List, Dict or Float argument causes an error.
+ Also see `and()` and `xor()`.
Example: >
:let bits = or(bits, 0x80)
< Can also be used as a |method|: >
:let bits = bits->or(0x80)
-pathshorten({expr} [, {len}]) *pathshorten()*
+< Rationale: The reason this is a function and not using the "|"
+ character like many languages, is that Vi has always used "|"
+ to separate commands. In many places it would not be clear if
+ "|" is an operator or a command separator.
+
+
+pathshorten({path} [, {len}]) *pathshorten()*
Shorten directory names in the path {path} and return the
result. The tail, the file name, is kept as-is. The other
components in the path are reduced to {len} letters in length.
@@ -6417,8 +6466,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 +6951,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 +6973,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 +7758,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")
@@ -8780,6 +8840,26 @@ virtcol({expr}) *virtcol()*
< Can also be used as a |method|: >
GetPos()->virtcol()
+virtcol2col({winid}, {lnum}, {col}) *virtcol2col()*
+ The result is a Number, which is the byte index of the
+ character in window {winid} at buffer line {lnum} and virtual
+ column {col}.
+
+ If {col} is greater than the last virtual column in line
+ {lnum}, then the byte index of the character at the last
+ virtual column is returned.
+
+ The {winid} argument can be the window number or the
+ |window-ID|. If this is zero, then the current window is used.
+
+ Returns -1 if the window {winid} doesn't exist or the buffer
+ line {lnum} or virtual column {col} is invalid.
+
+ See also |screenpos()|, |virtcol()| and |col()|.
+
+ Can also be used as a |method|: >
+ GetWinid()->virtcol2col(lnum, col)
+
visualmode([{expr}]) *visualmode()*
The result is a String, which describes the last Visual mode
used in the current buffer. Initially it returns an empty
@@ -9211,6 +9291,7 @@ writefile({object}, {fname} [, {flags}])
xor({expr}, {expr}) *xor()*
Bitwise XOR on the two arguments. The arguments are converted
to a number. A List, Dict or Float argument causes an error.
+ Also see `and()` and `or()`.
Example: >
:let bits = xor(bits, 0x80)
<
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/eval.txt b/runtime/doc/eval.txt
index 376adfec7f..3e068e3b4e 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2309,397 +2309,10 @@ help file: |builtin-functions|.
5. Defining functions *user-function*
New functions can be defined. These can be called just like builtin
-functions. The function executes a sequence of Ex commands. Normal mode
-commands can be executed with the |:normal| command.
-
-The function name must start with an uppercase letter, to avoid confusion with
-builtin functions. To prevent from using the same name in different scripts
-avoid obvious, short names. A good habit is to start the function name with
-the name of the script, e.g., "HTMLcolor()".
-
-It's also possible to use curly braces, see |curly-braces-names|. And the
-|autoload| facility is useful to define a function only when it's called.
-
- *local-function*
-A function local to a script must start with "s:". A local script function
-can only be called from within the script and from functions, user commands
-and autocommands defined in the script. It is also possible to call the
-function from a mapping defined in the script, but then |<SID>| must be used
-instead of "s:" when the mapping is expanded outside of the script.
-There are only script-local functions, no buffer-local or window-local
-functions.
-
- *:fu* *:function* *E128* *E129* *E123*
-:fu[nction] List all functions and their arguments.
-
-:fu[nction][!] {name} List function {name}, annotated with line numbers
- unless "!" is given.
- {name} may be a |Dictionary| |Funcref| entry: >
- :function dict.init
-
-:fu[nction] /{pattern} List functions with a name matching {pattern}.
- Example that lists all functions ending with "File": >
- :function /File$
-<
- *:function-verbose*
-When 'verbose' is non-zero, listing a function will also display where it was
-last defined. Example: >
-
- :verbose function SetFileTypeSH
- function SetFileTypeSH(name)
- Last set from /usr/share/vim/vim-7.0/filetype.vim
-<
-See |:verbose-cmd| for more information.
-
- *E124* *E125* *E853* *E884*
-:fu[nction][!] {name}([arguments]) [range] [abort] [dict] [closure]
- Define a new function by the name {name}. The body of
- the function follows in the next lines, until the
- matching |:endfunction|.
-
- The name must be made of alphanumeric characters and
- '_', and must start with a capital or "s:" (see
- above). Note that using "b:" or "g:" is not allowed.
- (since patch 7.4.260 E884 is given if the function
- name has a colon in the name, e.g. for "foo:bar()".
- Before that patch no error was given).
-
- {name} can also be a |Dictionary| entry that is a
- |Funcref|: >
- :function dict.init(arg)
-< "dict" must be an existing dictionary. The entry
- "init" is added if it didn't exist yet. Otherwise [!]
- is required to overwrite an existing function. The
- result is a |Funcref| to a numbered function. The
- function can only be used with a |Funcref| and will be
- deleted if there are no more references to it.
- *E127* *E122*
- When a function by this name already exists and [!] is
- not used an error message is given. There is one
- exception: When sourcing a script again, a function
- that was previously defined in that script will be
- silently replaced.
- When [!] is used, an existing function is silently
- replaced. Unless it is currently being executed, that
- is an error.
- NOTE: Use ! wisely. If used without care it can cause
- an existing function to be replaced unexpectedly,
- which is hard to debug.
-
- For the {arguments} see |function-argument|.
-
- *:func-range* *a:firstline* *a:lastline*
- When the [range] argument is added, the function is
- expected to take care of a range itself. The range is
- passed as "a:firstline" and "a:lastline". If [range]
- is excluded, ":{range}call" will call the function for
- each line in the range, with the cursor on the start
- of each line. See |function-range-example|.
- The cursor is still moved to the first line of the
- range, as is the case with all Ex commands.
- *:func-abort*
- When the [abort] argument is added, the function will
- abort as soon as an error is detected.
- *:func-dict*
- When the [dict] argument is added, the function must
- be invoked through an entry in a |Dictionary|. The
- local variable "self" will then be set to the
- dictionary. See |Dictionary-function|.
- *:func-closure* *E932*
- When the [closure] argument is added, the function
- can access variables and arguments from the outer
- scope. This is usually called a closure. In this
- example Bar() uses "x" from the scope of Foo(). It
- remains referenced even after Foo() returns: >
- :function! Foo()
- : let x = 0
- : function! Bar() closure
- : let x += 1
- : return x
- : endfunction
- : return funcref('Bar')
- :endfunction
-
- :let F = Foo()
- :echo F()
-< 1 >
- :echo F()
-< 2 >
- :echo F()
-< 3
-
- *function-search-undo*
- The last used search pattern and the redo command "."
- will not be changed by the function. This also
- implies that the effect of |:nohlsearch| is undone
- when the function returns.
-
- *:endf* *:endfunction* *E126* *E193* *W22*
-:endf[unction] [argument]
- The end of a function definition. Best is to put it
- on a line by its own, without [argument].
-
- [argument] can be:
- | command command to execute next
- \n command command to execute next
- " comment always ignored
- anything else ignored, warning given when
- 'verbose' is non-zero
- The support for a following command was added in Vim
- 8.0.0654, before that any argument was silently
- ignored.
-
- To be able to define a function inside an `:execute`
- command, use line breaks instead of |:bar|: >
- :exe "func Foo()\necho 'foo'\nendfunc"
-<
- *:delf* *:delfunction* *E131* *E933*
-:delf[unction][!] {name}
- Delete function {name}.
- {name} can also be a |Dictionary| entry that is a
- |Funcref|: >
- :delfunc dict.init
-< This will remove the "init" entry from "dict". The
- function is deleted if there are no more references to
- it.
- With the ! there is no error if the function does not
- exist.
- *:retu* *:return* *E133*
-:retu[rn] [expr] Return from a function. When "[expr]" is given, it is
- evaluated and returned as the result of the function.
- If "[expr]" is not given, the number 0 is returned.
- When a function ends without an explicit ":return",
- the number 0 is returned.
- Note that there is no check for unreachable lines,
- thus there is no warning if commands follow ":return".
-
- If the ":return" is used after a |:try| but before the
- matching |:finally| (if present), the commands
- following the ":finally" up to the matching |:endtry|
- are executed first. This process applies to all
- nested ":try"s inside the function. The function
- returns at the outermost ":endtry".
-
- *function-argument* *a:var*
-An argument can be defined by giving its name. In the function this can then
-be used as "a:name" ("a:" for argument).
- *a:0* *a:1* *a:000* *E740* *...*
-Up to 20 arguments can be given, separated by commas. After the named
-arguments an argument "..." can be specified, which means that more arguments
-may optionally be following. In the function the extra arguments can be used
-as "a:1", "a:2", etc. "a:0" is set to the number of extra arguments (which
-can be 0). "a:000" is set to a |List| that contains these arguments. Note
-that "a:1" is the same as "a:000[0]".
- *E742*
-The a: scope and the variables in it cannot be changed, they are fixed.
-However, if a composite type is used, such as |List| or |Dictionary| , you can
-change their contents. Thus you can pass a |List| to a function and have the
-function add an item to it. If you want to make sure the function cannot
-change a |List| or |Dictionary| use |:lockvar|.
-
-It is also possible to define a function without any arguments. You must
-still supply the () then.
-
-It is allowed to define another function inside a function body.
-
- *optional-function-argument*
-You can provide default values for positional named arguments. This makes
-them optional for function calls. When a positional argument is not
-specified at a call, the default expression is used to initialize it.
-This only works for functions declared with |function|, not for
-lambda expressions |expr-lambda|.
-
-Example: >
- function Something(key, value = 10)
- echo a:key .. ": " .. a:value
- endfunction
- call Something('empty') "empty: 10"
- call Something('key', 20) "key: 20"
-
-The argument default expressions are evaluated at the time of the function
-call, not definition. Thus it is possible to use an expression which is
-invalid the moment the function is defined. The expressions are also only
-evaluated when arguments are not specified during a call.
-
- *E989*
-Optional arguments with default expressions must occur after any mandatory
-arguments. You can use "..." after all optional named arguments.
-
-It is possible for later argument defaults to refer to prior arguments,
-but not the other way around. They must be prefixed with "a:", as with all
-arguments.
-
-Example that works: >
- :function Okay(mandatory, optional = a:mandatory)
- :endfunction
-Example that does NOT work: >
- :function NoGood(first = a:second, second = 10)
- :endfunction
-<
-When not using "...", the number of arguments in a function call must be at
-least equal to the number of mandatory named arguments. When using "...", the
-number of arguments may be larger than the total of mandatory and optional
-arguments.
-
- *local-variables*
-Inside a function local variables can be used. These will disappear when the
-function returns. Global variables need to be accessed with "g:".
-
-Example: >
- :function Table(title, ...)
- : echohl Title
- : echo a:title
- : echohl None
- : echo a:0 .. " items:"
- : for s in a:000
- : echon ' ' .. s
- : endfor
- :endfunction
-
-This function can then be called with: >
- call Table("Table", "line1", "line2")
- call Table("Empty Table")
-
-To return more than one value, return a |List|: >
- :function Compute(n1, n2)
- : if a:n2 == 0
- : return ["fail", 0]
- : endif
- : return ["ok", a:n1 / a:n2]
- :endfunction
-
-This function can then be called with: >
- :let [success, div] = Compute(102, 6)
- :if success == "ok"
- : echo div
- :endif
-<
- *:cal* *:call* *E107* *E117*
-:[range]cal[l] {name}([arguments])
- Call a function. The name of the function and its arguments
- are as specified with `:function`. Up to 20 arguments can be
- used. The returned value is discarded.
- Without a range and for functions that accept a range, the
- function is called once. When a range is given the cursor is
- positioned at the start of the first line before executing the
- function.
- When a range is given and the function doesn't handle it
- itself, the function is executed for each line in the range,
- with the cursor in the first column of that line. The cursor
- is left at the last line (possibly moved by the last function
- call). The arguments are re-evaluated for each line. Thus
- this works:
- *function-range-example* >
- :function Mynumber(arg)
- : echo line(".") .. " " .. a:arg
- :endfunction
- :1,5call Mynumber(getline("."))
-<
- The "a:firstline" and "a:lastline" are defined anyway, they
- can be used to do something different at the start or end of
- the range.
-
- Example of a function that handles the range itself: >
-
- :function Cont() range
- : execute (a:firstline + 1) .. "," .. a:lastline .. 's/^/\t\\ '
- :endfunction
- :4,8call Cont()
-<
- This function inserts the continuation character "\" in front
- of all the lines in the range, except the first one.
-
- When the function returns a composite value it can be further
- dereferenced, but the range will not be used then. Example: >
- :4,8call GetDict().method()
-< Here GetDict() gets the range but method() does not.
-
- *E132*
-The recursiveness of user functions is restricted with the |'maxfuncdepth'|
-option.
-
-It is also possible to use `:eval`. It does not support a range, but does
-allow for method chaining, e.g.: >
- eval GetList()->Filter()->append('$')
+functions. The function takes arguments, executes a sequence of Ex commands
+and can return a value.
-
-AUTOMATICALLY LOADING FUNCTIONS ~
- *autoload-functions*
-When using many or large functions, it's possible to automatically define them
-only when they are used. There are two methods: with an autocommand and with
-the "autoload" directory in 'runtimepath'.
-
-
-Using an autocommand ~
-
-This is introduced in the user manual, section |41.14|.
-
-The autocommand is useful if you have a plugin that is a long Vim script file.
-You can define the autocommand and quickly quit the script with `:finish`.
-That makes Vim startup faster. The autocommand should then load the same file
-again, setting a variable to skip the `:finish` command.
-
-Use the FuncUndefined autocommand event with a pattern that matches the
-function(s) to be defined. Example: >
-
- :au FuncUndefined BufNet* source ~/vim/bufnetfuncs.vim
-
-The file "~/vim/bufnetfuncs.vim" should then define functions that start with
-"BufNet". Also see |FuncUndefined|.
-
-
-Using an autoload script ~
- *autoload* *E746*
-This is introduced in the user manual, section |41.15|.
-
-Using a script in the "autoload" directory is simpler, but requires using
-exactly the right file name. A function that can be autoloaded has a name
-like this: >
-
- :call filename#funcname()
-
-When such a function is called, and it is not defined yet, Vim will search the
-"autoload" directories in 'runtimepath' for a script file called
-"filename.vim". For example "~/.config/nvim/autoload/filename.vim". That
-file should then define the function like this: >
-
- function filename#funcname()
- echo "Done!"
- endfunction
-
-The file name and the name used before the # in the function must match
-exactly, and the defined function must have the name exactly as it will be
-called.
-
-It is possible to use subdirectories. Every # in the function name works like
-a path separator. Thus when calling a function: >
-
- :call foo#bar#func()
-
-Vim will look for the file "autoload/foo/bar.vim" in 'runtimepath'.
-
-This also works when reading a variable that has not been set yet: >
-
- :let l = foo#bar#lvar
-
-However, when the autoload script was already loaded it won't be loaded again
-for an unknown variable.
-
-When assigning a value to such a variable nothing special happens. This can
-be used to pass settings to the autoload script before it's loaded: >
-
- :let foo#bar#toggle = 1
- :call foo#bar#func()
-
-Note that when you make a mistake and call a function that is supposed to be
-defined in an autoload script, but the script doesn't actually define the
-function, you will get an error message for the missing function. If you fix
-the autoload script it won't be automatically loaded again. Either restart
-Vim or manually source the script.
-
-Also note that if you have two script files, and one calls a function in the
-other and vice versa, before the used function is defined, it won't work.
-Avoid using the autoload functionality at the toplevel.
+You can find most information about defining functions in |userfunc.txt|.
==============================================================================
6. Curly braces names *curly-braces-names*
@@ -3167,6 +2780,9 @@ text...
iterate over. Unlike with |List|, modifying the
|Blob| does not affect the iteration.
+ When {object} is a |String| each item is a string with
+ one character, plus any combining characters.
+
:for [{var1}, {var2}, ...] in {listlist}
:endfo[r]
Like `:for` above, but each item in {listlist} must be
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index 7fff74a963..9f8ef248f8 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -586,12 +586,12 @@ Local mappings:
to the end of the file in Normal mode. This means "> " is inserted in
each line.
-MAN *ft-man-plugin* *:Man* *man.vim*
+MAN *ft-man-plugin* *:Man* *man.lua*
View manpages in Nvim. Supports highlighting, completion, locales, and
navigation. Also see |find-manpage|.
-man.vim will always attempt to reuse the closest man window (above/left) but
+man.lua will always attempt to reuse the closest man window (above/left) but
otherwise create a split.
The case sensitivity of completion is controlled by 'fileignorecase'.
diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt
index 04e31e0680..34213f7512 100644
--- a/runtime/doc/help.txt
+++ b/runtime/doc/help.txt
@@ -131,6 +131,7 @@ Advanced editing ~
|autocmd.txt| automatically executing commands on an event
|eval.txt| expression evaluation, conditional commands
|builtin.txt| builtin functions
+|userfunc.txt| defining user functions
|fold.txt| hide (fold) ranges of lines
|lua.txt| Lua API
|api.txt| Nvim API via RPC, Lua and VimL
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..00aaf759e2 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
@@ -1128,6 +1136,11 @@ format({options}) *vim.lsp.buf.format()*
ID (client.id) matching this field.
• name (string|nil): Restrict formatting to the client with
name (client.name) matching this field.
+ • range (table|nil) Range to format. Table must contain
+ `start` and `end` keys with {row, col} tuples using (1,0)
+ indexing. Defaults to current selection in visual mode
+ Defaults to `nil` in other modes, formatting the full
+ buffer
formatting({options}) *vim.lsp.buf.formatting()*
Formats the current buffer.
@@ -1890,6 +1903,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 +1928,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 +1939,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
@@ -1937,8 +1962,9 @@ rpc_response_error({code}, {message}, {data})
*vim.lsp.rpc.start()*
start({cmd}, {cmd_args}, {dispatchers}, {extra_spawn_params})
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.
+ interact with it. Communication with the spawned process happens via
+ stdio. For communication via TCP, spawn a process manually and use
+ |vim.lsp.rpc.connect|
Parameters: ~
{cmd} (string) Command to start the LSP server.
@@ -1962,11 +1988,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..35badb13b1 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.
@@ -951,6 +967,37 @@ vim.wait({time} [, {callback}, {interval}, {fast_only}]) *vim.wait()*
end
<
+vim.ui_attach({ns}, {options}, {callback}) *vim.ui_attach()*
+ Attach to ui events, similar to |nvim_ui_attach()| but receive events
+ as lua callback. Can be used to implement screen elements like
+ popupmenu or message handling in lua.
+
+ {options} should be a dictionary-like table, where `ext_...` options should
+ be set to true to receive events for the respective external element.
+
+ {callback} receives event name plus additional parameters. See |ui-popupmenu|
+ and the sections below for event format for respective events.
+
+ Example (stub for a |ui-popupmenu| implementation): >
+
+ ns = vim.api.nvim_create_namespace('my_fancy_pum')
+
+ vim.ui_attach(ns, {ext_popupmenu=true}, function(event, ...)
+ if event == "popupmenu_show" then
+ local items, selected, row, col, grid = ...
+ print("display pum ", #items)
+ elseif event == "popupmenu_select" then
+ local selected = ...
+ print("selected", selected)
+ elseif event == "popupmenu_hide" then
+ print("FIN")
+ end
+ end)
+
+vim.ui_detach({ns}) *vim.ui_detach()*
+ Detach a callback previously attached with |vim.ui_attach()| for the
+ given namespace {ns}.
+
vim.type_idx *vim.type_idx*
Type index for use in |lua-special-tbl|. Specifying one of the values from
|vim.types| allows typing the empty table (it is unclear whether empty Lua
@@ -1075,17 +1122,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 +1137,145 @@ from within Lua.
`set number`
In Lua:
- `vim.opt.number = true`
+ `vim.o.number = true`
- To set an array of values:
+ To set a string value:
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:
+ `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.
- However, vim.opt also supports a more elegent way of setting
- list-style options by using lua tables:
+ 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: ~
+
+ The following methods of setting a list-style option are equivalent:
+ In Vimscript:
+ `set wildignore=*.o,*.a,__pycache__`
+
+ In Lua using `vim.o`:
+ `vim.o.wildignore = '*.o,*.a,__pycache__'`
+
+ 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 +1288,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 +1301,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 +1312,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 +1348,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*
@@ -1520,6 +1581,28 @@ deepcopy({orig}) *vim.deepcopy()*
Return: ~
(table) Table of copied keys and (nested) values.
+defaulttable({create}) *vim.defaulttable()*
+ Creates a table whose members are automatically created when accessed, if
+ they don't already exist.
+
+ They mimic defaultdict in python.
+
+ If `create` is `nil`, this will create a defaulttable whose constructor
+ function is this function, effectively allowing to create nested tables on
+ the fly:
+>
+
+ local a = vim.defaulttable()
+ a.b.c = 1
+<
+
+ Parameters: ~
+ {create} (function|nil) The function called to create a missing
+ value.
+
+ Return: ~
+ (table) Empty table with metamethod
+
endswith({s}, {suffix}) *vim.endswith()*
Tests if `s` ends with `suffix`.
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index ca1ddaabd4..da6a305e89 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -1623,11 +1623,11 @@ The valid escape sequences are
*<mods>* *<q-mods>* *:command-modifiers*
<mods> The command modifiers, if specified. Otherwise, expands to
nothing. Supported modifiers are |:aboveleft|, |:belowright|,
- |:botright|, |:browse|, |:confirm|, |:hide|, |:keepalt|,
- |:keepjumps|, |:keepmarks|, |:keeppatterns|, |:leftabove|,
- |:lockmarks|, |:noautocmd|, |:noswapfile| |:rightbelow|,
- |:sandbox|, |:silent|, |:tab|, |:topleft|, |:unsilent|,
- |:verbose|, and |:vertical|.
+ |:botright|, |:browse|, |:confirm|, |:hide|, |:horizontal|,
+ |:keepalt|, |:keepjumps|, |:keepmarks|, |:keeppatterns|,
+ |:leftabove|, |:lockmarks|, |:noautocmd|, |:noswapfile|
+ |:rightbelow|, |:sandbox|, |:silent|, |:tab|, |:topleft|,
+ |:unsilent|, |:verbose|, and |:vertical|.
Note that |:filter| is not supported.
Examples: >
command! -nargs=+ -complete=file MyEdit
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 2e0c1f8cc4..87d2abeece 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1350,7 +1350,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'colorcolumn' 'cc' string (default "")
local to window
'colorcolumn' is a comma-separated list of screen columns that are
- highlighted with ColorColumn |hl-ColorColumn|. Useful to align
+ highlighted with ColorColumn |hl-ColorColumn| and drawn using the
+ "colorcol" option from 'fillchars'. Useful to align
text. Will make screen redrawing slower.
The screen column can be an absolute number, or a number preceded with
'+' or '-', which is added to or subtracted from 'textwidth'. >
@@ -2454,28 +2455,31 @@ 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
+ colorcol ' ' character to display in the colorcolumn
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 +2504,20 @@ 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|
+ colorcol:c ColorColumn |hl-ColorColumn|
*'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'*
'fixendofline' 'fixeol' boolean (default on)
@@ -4229,6 +4234,15 @@ A jump table for the options with a short description can be found at |Q_op|.
The 'mousemodel' option is set by the |:behave| command.
+ *'mousemoveevent'* *'mousemev'*
+'mousemoveevent' 'mousemev' boolean (default off)
+ global
+ When on, mouse move events are delivered to the input queue and are
+ available for mapping. The default, off, avoids the mouse movement
+ overhead except when needed.
+ Warning: Setting this option can make pending mappings to be aborted
+ when the mouse is moved.
+
*'mousescroll'*
'mousescroll' string (default "ver:3,hor:6")
global
@@ -5860,10 +5874,14 @@ A jump table for the options with a short description can be found at |Q_op|.
'spelloptions' 'spo' string (default "")
local to buffer
A comma-separated list of options for spell checking:
- camel When a word is CamelCased, assume "Cased" is a
+ camel When a word is CamelCased, assume "Cased" is a
separate word: every upper-case character in a word
that comes after a lower case character indicates the
start of a new word.
+ noplainbuffer Only spellcheck a buffer when 'syntax' is enabled,
+ or when extmarks are set within the buffer. Only
+ designated regions of the buffer are spellchecked in
+ this case.
*'spellsuggest'* *'sps'*
'spellsuggest' 'sps' string (default "best")
@@ -6722,6 +6740,57 @@ A jump table for the options with a short description can be found at |Q_op|.
written to disk (see |crash-recovery|). Also used for the
|CursorHold| autocommand event.
+ *'userregfunc'* *'urf'*
+'userregfunc' 'urf' string (default "")
+ global
+ The option specifies a function to be used to handle any registers
+ that Neovim does not natively handle. This option unlocks all
+ characters to be used as registers by the user.
+
+ The 'userregfunc' function is called each time a user register is read
+ from or written to.
+
+ The 'userregfunc' function must take the following parameters:
+
+ {action} The action being done on this register (either 'yank'
+ or 'put'
+
+ {register} The string holding the name of the register. This
+ is always a single character, though multi-byte
+ characters are allowed.
+
+ {content} If the action is 'yank' this is the content being
+ yanked into the register. The content is a dictionary
+ with the following items:
+
+ {lines} The lines being yanked, as a list.
+
+ {type} The type of yank, either "line", "char", or
+ "block"
+
+ {width} The width in case of "block" mode.
+
+ {additional_data} Additional data. (can be returned in
+ put mode).
+
+ In case the action is 'put', the 'userregfunc' function should return
+ the content to place in that location. The content can either be a
+ string, in which case "char" mode is inferred, or it can return a
+ dictionary of the same template that populates 'content'.
+
+ A very simple example of a 'userregfunc' function that behaves exactly
+ like traditional registers would look like: >
+
+ let s:contents = {}
+ function! MyUserregFunction(action, register, content) abort
+ if a:action == "put"
+ return get(s:contents, a:register, "")
+ else
+ let s:contents[a:register] = a:content
+ endif
+ endfunction
+ set userregfunc=MyUserregFunction
+<
*'varsofttabstop'* *'vsts'*
'varsofttabstop' 'vsts' string (default "")
local to buffer
@@ -6938,15 +7007,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/quickref.txt b/runtime/doc/quickref.txt
index 6f16db5cc2..9f3993506a 100644
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -649,6 +649,7 @@ Short explanation of each option: *option-list*
'complete' 'cpt' specify how Insert mode completion works
'completefunc' 'cfu' function to be used for Insert mode completion
'completeopt' 'cot' options for Insert mode completion
+'completeslash' 'csl' like 'shellslash' for completion
'concealcursor' 'cocu' whether concealable text is hidden in cursor line
'conceallevel' 'cole' whether concealable text is shown or hidden
'confirm' 'cf' ask what to do about unsaved/read-only files
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/tagsrch.txt b/runtime/doc/tagsrch.txt
index 2485290667..82deb0fa0c 100644
--- a/runtime/doc/tagsrch.txt
+++ b/runtime/doc/tagsrch.txt
@@ -870,13 +870,15 @@ like |CTRL-]|.
The function used for generating the taglist is specified by setting the
'tagfunc' option. The function will be called with three arguments:
- a:pattern The tag identifier or pattern used during the tag search.
- a:flags String containing flags to control the function behavior.
- a:info Dict containing the following entries:
+ pattern The tag identifier or pattern used during the tag search.
+ flags String containing flags to control the function behavior.
+ info Dict containing the following entries:
buf_ffname Full filename which can be used for priority.
user_data Custom data String, if stored in the tag
stack previously by tagfunc.
+Note that "a:" needs to be prepended to the argument name when using it.
+
Currently up to three flags may be passed to the tag function:
'c' The function was invoked by a normal command being processed
(mnemonic: the tag function may use the context around the
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 52531a1525..491aea793c 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -187,6 +187,11 @@ Note: The predicates listed in the web page above differ from those Neovim
supports. See |lua-treesitter-predicates| for a complete list of predicates
supported by Neovim.
+By default, the first query on `runtimepath` is used (which usually implies
+that user config takes precedence over plugins, which take precedence over
+queries bundled with Neovim). If a query should extend other queries instead
+of replacing them, use |ts-modeline-extends|.
+
A `query` consists of one or more patterns. A `pattern` is defined over node
types in the syntax tree. A `match` corresponds to specific elements of the
syntax tree which match a pattern. Patterns may optionally define captures
@@ -194,6 +199,36 @@ and predicates. A `capture` allows you to associate names with a specific
node in a pattern. A `predicate` adds arbitrary metadata and conditional data
to a match.
+ *ts-query-modeline*
+Neovim supports to customize the behavior of the queries using a set of
+"modelines", that is comments in the queries starting with `;`. Here are the
+currently supported modeline alternatives:
+
+ `inherits: {lang}...` *ts-modeline-inherits*
+ Specifies that this query should inherit the queries from {lang}.
+ This will recursively descend in the queries of {lang} unless wrapped
+ in parentheses: `({lang})`.
+ Note: this is meant to be used to include queries from another
+ language. If you want your query to extend the queries of the same
+ language, use `extends`.
+
+ `extends` *ts-modeline-extends*
+ Specifies that this query should be used as an extension for the
+ query, i.e. that it should be merged with the others.
+ Note: the order of the extensions, and the query that will be used as
+ a base depends on your 'runtimepath' value.
+
+Note: these modeline comments must be at the top of the query, but can be
+repeated, for example, the following modeline blocks are all valid:
+>
+ ;; inherits: foo,bar
+ ;; extends
+
+ ;; extends
+ ;;
+ ;; inherits: baz
+<
+
Treesitter Query Predicates *lua-treesitter-predicates*
When writing queries for treesitter, one might use `predicates`, that is,
@@ -323,16 +358,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 +405,60 @@ attribute: >
==============================================================================
Lua module: vim.treesitter *lua-treesitter-core*
+get_captures_at_cursor({winnr}) *get_captures_at_cursor()*
+ Gets a list of captures under the cursor
+
+ Parameters: ~
+ {winnr} (number|nil) Window handle or 0 for current window (default)
+
+ Return: ~
+ (table) Named node under the cursor
+
+ *get_captures_at_position()*
+get_captures_at_position({bufnr}, {row}, {col})
+ Gets a list of captures for a given cursor position
+
+ Parameters: ~
+ {bufnr} (number) Buffer number (0 for current buffer)
+ {row} (number) Position row
+ {col} (number) Position column
+
+ Return: ~
+ (table) Table of captures
+
+get_node_at_cursor({winnr}) *get_node_at_cursor()*
+ Gets the smallest named node under the cursor
+
+ Parameters: ~
+ {winnr} (number|nil) Window handle or 0 for current window (default)
+
+ Return: ~
+ (string) Named node under the cursor
+
+ *get_node_at_position()*
+get_node_at_position({bufnr}, {row}, {col}, {opts})
+ Gets the smallest named node at position
+
+ Parameters: ~
+ {bufnr} (number) Buffer number (0 for current buffer)
+ {row} (number) Position row
+ {col} (number) Position column
+ {opts} (table) Optional keyword arguments:
+ • ignore_injections boolean Ignore injected languages
+ (default true)
+
+ Return: ~
+ (table) Named node under the cursor
+
+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: ~
+ (table) start_row, start_col, end_row, end_col
+
get_parser({bufnr}, {lang}, {opts}) *get_parser()*
Gets the parser for this bufnr / ft combination.
@@ -359,12 +466,14 @@ get_parser({bufnr}, {lang}, {opts}) *get_parser()*
callback
Parameters: ~
- {bufnr} The buffer the parser should be tied to
- {lang} The filetype of this parser
- {opts} Options object to pass to the created language tree
+ {bufnr} (number|nil) Buffer the parser should be tied to (default:
+ current buffer)
+ {lang} (string) |nil Filetype of this parser (default: buffer
+ filetype)
+ {opts} (table|nil) Options to pass to the created language tree
Return: ~
- The parser
+ (table) Parser object
get_string_parser({str}, {lang}, {opts}) *get_string_parser()*
Gets a string parser
@@ -374,6 +483,70 @@ 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) Possible ancestor
+ {source} (table) 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} (table) Node defining the range
+ {line} (number) Line (0-based)
+ {col} (number) Column (0-based)
+
+ Return: ~
+ (boolean) True if the position is in node range
+
+node_contains({node}, {range}) *node_contains()*
+ Determines if a node contains a range
+
+ Parameters: ~
+ {node} (table)
+ {range} (table)
+
+ Return: ~
+ (boolean) True if the node contains the range
+
+start({bufnr}, {lang}) *start()*
+ Start treesitter highlighting for a buffer
+
+ Can be used in an ftplugin or FileType autocommand
+
+ Note: By default, disables regex syntax highlighting, which may be
+ required for some plugins. In this case, add `vim.bo.syntax = 'on'` after
+ the call to `start`.
+
+ Example:
+>
+
+ vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex',
+ callback = function(args)
+ vim.treesitter.start(args.buf, 'latex')
+ vim.bo[args.buf].syntax = 'on' -- only if additional legacy syntax is needed
+ end
+ })
+<
+
+ Parameters: ~
+ {bufnr} (number|nil) Buffer to be highlighted (default: current
+ buffer)
+ {lang} (string|nil) Language of the parser (default: buffer
+ filetype)
+
+stop({bufnr}) *stop()*
+ Stop treesitter highlighting for a buffer
+
+ Parameters: ~
+ {bufnr} (number|nil) Buffer to stop highlighting (default: current
+ buffer)
+
==============================================================================
Lua module: vim.treesitter.language *treesitter-language*
@@ -387,16 +560,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 +600,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 +857,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 +928,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/ui.txt b/runtime/doc/ui.txt
index 3fb9ed1125..955af84679 100644
--- a/runtime/doc/ui.txt
+++ b/runtime/doc/ui.txt
@@ -207,6 +207,7 @@ the editor.
'guifontwide'
'linespace'
'mousefocus'
+ 'mousemoveevent'
'pumblend'
'showtabline'
'termguicolors'
diff --git a/runtime/doc/userfunc.txt b/runtime/doc/userfunc.txt
new file mode 100644
index 0000000000..c701834383
--- /dev/null
+++ b/runtime/doc/userfunc.txt
@@ -0,0 +1,429 @@
+*userfunc.txt* Nvim
+
+
+ VIM REFERENCE MANUAL by Bram Moolenaar
+
+
+Defining and using functions.
+
+This is introduced in section |41.7| of the user manual.
+
+ Type |gO| to see the table of contents.
+
+==============================================================================
+
+1. Defining a fuction ~
+ *define-function*
+New functions can be defined. These can be called just like builtin
+functions. The function executes a sequence of Ex commands. Normal mode
+commands can be executed with the |:normal| command.
+
+The function name must start with an uppercase letter, to avoid confusion with
+builtin functions. To prevent from using the same name in different scripts
+make them script-local. If you do use a global function then avoid obvious,
+short names. A good habit is to start the function name with the name of the
+script, e.g., "HTMLcolor()".
+
+It is also possible to use curly braces, see |curly-braces-names|.
+
+The |autoload| facility is useful to define a function only when it's called.
+
+ *local-function*
+A function local to a script must start with "s:". A local script function
+can only be called from within the script and from functions, user commands
+and autocommands defined in the script. It is also possible to call the
+function from a mapping defined in the script, but then |<SID>| must be used
+instead of "s:" when the mapping is expanded outside of the script.
+There are only script-local functions, no buffer-local or window-local
+functions.
+
+ *:fu* *:function* *E128* *E129* *E123*
+:fu[nction] List all functions and their arguments.
+
+:fu[nction][!] {name} List function {name}, annotated with line numbers
+ unless "!" is given.
+ {name} may be a |Dictionary| |Funcref| entry: >
+ :function dict.init
+
+:fu[nction] /{pattern} List functions with a name matching {pattern}.
+ Example that lists all functions ending with "File": >
+ :function /File$
+<
+ *:function-verbose*
+When 'verbose' is non-zero, listing a function will also display where it was
+last defined. Example: >
+
+ :verbose function SetFileTypeSH
+ function SetFileTypeSH(name)
+ Last set from /usr/share/vim/vim-7.0/filetype.vim
+<
+See |:verbose-cmd| for more information.
+
+ *E124* *E125* *E853* *E884*
+:fu[nction][!] {name}([arguments]) [range] [abort] [dict] [closure]
+ Define a new function by the name {name}. The body of
+ the function follows in the next lines, until the
+ matching |:endfunction|.
+
+ The name must be made of alphanumeric characters and
+ '_', and must start with a capital or "s:" (see
+ above). Note that using "b:" or "g:" is not allowed.
+ (since patch 7.4.260 E884 is given if the function
+ name has a colon in the name, e.g. for "foo:bar()".
+ Before that patch no error was given).
+
+ {name} can also be a |Dictionary| entry that is a
+ |Funcref|: >
+ :function dict.init(arg)
+< "dict" must be an existing dictionary. The entry
+ "init" is added if it didn't exist yet. Otherwise [!]
+ is required to overwrite an existing function. The
+ result is a |Funcref| to a numbered function. The
+ function can only be used with a |Funcref| and will be
+ deleted if there are no more references to it.
+ *E127* *E122*
+ When a function by this name already exists and [!] is
+ not used an error message is given. There is one
+ exception: When sourcing a script again, a function
+ that was previously defined in that script will be
+ silently replaced.
+ When [!] is used, an existing function is silently
+ replaced. Unless it is currently being executed, that
+ is an error.
+ NOTE: Use ! wisely. If used without care it can cause
+ an existing function to be replaced unexpectedly,
+ which is hard to debug.
+
+ For the {arguments} see |function-argument|.
+
+ *:func-range* *a:firstline* *a:lastline*
+ When the [range] argument is added, the function is
+ expected to take care of a range itself. The range is
+ passed as "a:firstline" and "a:lastline". If [range]
+ is excluded, ":{range}call" will call the function for
+ each line in the range, with the cursor on the start
+ of each line. See |function-range-example|.
+ The cursor is still moved to the first line of the
+ range, as is the case with all Ex commands.
+ *:func-abort*
+ When the [abort] argument is added, the function will
+ abort as soon as an error is detected.
+ *:func-dict*
+ When the [dict] argument is added, the function must
+ be invoked through an entry in a |Dictionary|. The
+ local variable "self" will then be set to the
+ dictionary. See |Dictionary-function|.
+ *:func-closure* *E932*
+ When the [closure] argument is added, the function
+ can access variables and arguments from the outer
+ scope. This is usually called a closure. In this
+ example Bar() uses "x" from the scope of Foo(). It
+ remains referenced even after Foo() returns: >
+ :function! Foo()
+ : let x = 0
+ : function! Bar() closure
+ : let x += 1
+ : return x
+ : endfunction
+ : return funcref('Bar')
+ :endfunction
+
+ :let F = Foo()
+ :echo F()
+< 1 >
+ :echo F()
+< 2 >
+ :echo F()
+< 3
+
+ *function-search-undo*
+ The last used search pattern and the redo command "."
+ will not be changed by the function. This also
+ implies that the effect of |:nohlsearch| is undone
+ when the function returns.
+
+ *:endf* *:endfunction* *E126* *E193* *W22*
+:endf[unction] [argument]
+ The end of a function definition. Best is to put it
+ on a line by its own, without [argument].
+
+ [argument] can be:
+ | command command to execute next
+ \n command command to execute next
+ " comment always ignored
+ anything else ignored, warning given when
+ 'verbose' is non-zero
+ The support for a following command was added in Vim
+ 8.0.0654, before that any argument was silently
+ ignored.
+
+ To be able to define a function inside an `:execute`
+ command, use line breaks instead of |:bar|: >
+ :exe "func Foo()\necho 'foo'\nendfunc"
+<
+ *:delf* *:delfunction* *E131* *E933*
+:delf[unction][!] {name}
+ Delete function {name}.
+ {name} can also be a |Dictionary| entry that is a
+ |Funcref|: >
+ :delfunc dict.init
+< This will remove the "init" entry from "dict". The
+ function is deleted if there are no more references to
+ it.
+ With the ! there is no error if the function does not
+ exist.
+ *:retu* *:return* *E133*
+:retu[rn] [expr] Return from a function. When "[expr]" is given, it is
+ evaluated and returned as the result of the function.
+ If "[expr]" is not given, the number 0 is returned.
+ When a function ends without an explicit ":return",
+ the number 0 is returned.
+ Note that there is no check for unreachable lines,
+ thus there is no warning if commands follow ":return".
+
+ If the ":return" is used after a |:try| but before the
+ matching |:finally| (if present), the commands
+ following the ":finally" up to the matching |:endtry|
+ are executed first. This process applies to all
+ nested ":try"s inside the function. The function
+ returns at the outermost ":endtry".
+
+ *function-argument* *a:var*
+An argument can be defined by giving its name. In the function this can then
+be used as "a:name" ("a:" for argument).
+ *a:0* *a:1* *a:000* *E740* *...*
+Up to 20 arguments can be given, separated by commas. After the named
+arguments an argument "..." can be specified, which means that more arguments
+may optionally be following. In the function the extra arguments can be used
+as "a:1", "a:2", etc. "a:0" is set to the number of extra arguments (which
+can be 0). "a:000" is set to a |List| that contains these arguments. Note
+that "a:1" is the same as "a:000[0]".
+ *E742*
+The a: scope and the variables in it cannot be changed, they are fixed.
+However, if a composite type is used, such as |List| or |Dictionary| , you can
+change their contents. Thus you can pass a |List| to a function and have the
+function add an item to it. If you want to make sure the function cannot
+change a |List| or |Dictionary| use |:lockvar|.
+
+It is also possible to define a function without any arguments. You must
+still supply the () then.
+
+It is allowed to define another function inside a function body.
+
+ *optional-function-argument*
+You can provide default values for positional named arguments. This makes
+them optional for function calls. When a positional argument is not
+specified at a call, the default expression is used to initialize it.
+This only works for functions declared with |function|, not for
+lambda expressions |expr-lambda|.
+
+Example: >
+ function Something(key, value = 10)
+ echo a:key .. ": " .. a:value
+ endfunction
+ call Something('empty') "empty: 10"
+ call Something('key', 20) "key: 20"
+
+The argument default expressions are evaluated at the time of the function
+call, not definition. Thus it is possible to use an expression which is
+invalid the moment the function is defined. The expressions are also only
+evaluated when arguments are not specified during a call.
+
+ *E989*
+Optional arguments with default expressions must occur after any mandatory
+arguments. You can use "..." after all optional named arguments.
+
+It is possible for later argument defaults to refer to prior arguments,
+but not the other way around. They must be prefixed with "a:", as with all
+arguments.
+
+Example that works: >
+ :function Okay(mandatory, optional = a:mandatory)
+ :endfunction
+Example that does NOT work: >
+ :function NoGood(first = a:second, second = 10)
+ :endfunction
+<
+When not using "...", the number of arguments in a function call must be at
+least equal to the number of mandatory named arguments. When using "...", the
+number of arguments may be larger than the total of mandatory and optional
+arguments.
+
+ *local-variables*
+Inside a function local variables can be used. These will disappear when the
+function returns. Global variables need to be accessed with "g:". Inside
+functions local variables are accessed without prepending anything. But you
+can also prepend "l:" if you like. This is required for some reserved names,
+such as "version".
+
+Example: >
+ :function Table(title, ...)
+ : echohl Title
+ : echo a:title
+ : echohl None
+ : echo a:0 .. " items:"
+ : for s in a:000
+ : echon ' ' .. s
+ : endfor
+ :endfunction
+
+This function can then be called with: >
+ call Table("Table", "line1", "line2")
+ call Table("Empty Table")
+
+To return more than one value, return a |List|: >
+ :function Compute(n1, n2)
+ : if a:n2 == 0
+ : return ["fail", 0]
+ : endif
+ : return ["ok", a:n1 / a:n2]
+ :endfunction
+
+This function can then be called with: >
+ :let [success, div] = Compute(102, 6)
+ :if success == "ok"
+ : echo div
+ :endif
+<
+==============================================================================
+
+2. Calling a fuction ~
+ *:cal* *:call* *E107* *E117*
+:[range]cal[l] {name}([arguments])
+ Call a function. The name of the function and its arguments
+ are as specified with `:function`. Up to 20 arguments can be
+ used. The returned value is discarded.
+ Without a range and for functions that accept a range, the
+ function is called once. When a range is given the cursor is
+ positioned at the start of the first line before executing the
+ function.
+ When a range is given and the function doesn't handle it
+ itself, the function is executed for each line in the range,
+ with the cursor in the first column of that line. The cursor
+ is left at the last line (possibly moved by the last function
+ call). The arguments are re-evaluated for each line. Thus
+ this works:
+ *function-range-example* >
+ :function Mynumber(arg)
+ : echo line(".") .. " " .. a:arg
+ :endfunction
+ :1,5call Mynumber(getline("."))
+<
+ The "a:firstline" and "a:lastline" are defined anyway, they
+ can be used to do something different at the start or end of
+ the range.
+
+ Example of a function that handles the range itself: >
+
+ :function Cont() range
+ : execute (a:firstline + 1) .. "," .. a:lastline .. 's/^/\t\\ '
+ :endfunction
+ :4,8call Cont()
+<
+ This function inserts the continuation character "\" in front
+ of all the lines in the range, except the first one.
+
+ When the function returns a composite value it can be further
+ dereferenced, but the range will not be used then. Example: >
+ :4,8call GetDict().method()
+< Here GetDict() gets the range but method() does not.
+
+ *E132*
+The recursiveness of user functions is restricted with the |'maxfuncdepth'|
+option.
+
+It is also possible to use `:eval`. It does not support a range, but does
+allow for method chaining, e.g.: >
+ eval GetList()->Filter()->append('$')
+
+A function can also be called as part of evaluating an expression or when it
+is used as a method: >
+ let x = GetList()
+ let y = GetList()->Filter()
+
+
+==============================================================================
+
+3. Automatically loading functions ~
+ *autoload-functions*
+When using many or large functions, it's possible to automatically define them
+only when they are used. There are two methods: with an autocommand and with
+the "autoload" directory in 'runtimepath'.
+
+
+Using an autocommand ~
+
+This is introduced in the user manual, section |41.14|.
+
+The autocommand is useful if you have a plugin that is a long Vim script file.
+You can define the autocommand and quickly quit the script with `:finish`.
+That makes Vim startup faster. The autocommand should then load the same file
+again, setting a variable to skip the `:finish` command.
+
+Use the FuncUndefined autocommand event with a pattern that matches the
+function(s) to be defined. Example: >
+
+ :au FuncUndefined BufNet* source ~/vim/bufnetfuncs.vim
+
+The file "~/vim/bufnetfuncs.vim" should then define functions that start with
+"BufNet". Also see |FuncUndefined|.
+
+
+Using an autoload script ~
+ *autoload* *E746*
+This is introduced in the user manual, section |41.15|.
+
+Using a script in the "autoload" directory is simpler, but requires using
+exactly the right file name. A function that can be autoloaded has a name
+like this: >
+
+ :call filename#funcname()
+
+When such a function is called, and it is not defined yet, Vim will search the
+"autoload" directories in 'runtimepath' for a script file called
+"filename.vim". For example "~/.config/nvim/autoload/filename.vim". That
+file should then define the function like this: >
+
+ function filename#funcname()
+ echo "Done!"
+ endfunction
+
+The file name and the name used before the # in the function must match
+exactly, and the defined function must have the name exactly as it will be
+called.
+
+It is possible to use subdirectories. Every # in the function name works like
+a path separator. Thus when calling a function: >
+
+ :call foo#bar#func()
+
+Vim will look for the file "autoload/foo/bar.vim" in 'runtimepath'.
+
+This also works when reading a variable that has not been set yet: >
+
+ :let l = foo#bar#lvar
+
+However, when the autoload script was already loaded it won't be loaded again
+for an unknown variable.
+
+When assigning a value to such a variable nothing special happens. This can
+be used to pass settings to the autoload script before it's loaded: >
+
+ :let foo#bar#toggle = 1
+ :call foo#bar#func()
+
+Note that when you make a mistake and call a function that is supposed to be
+defined in an autoload script, but the script doesn't actually define the
+function, you will get an error message for the missing function. If you fix
+the autoload script it won't be automatically loaded again. Either restart
+Vim or manually source the script.
+
+Also note that if you have two script files, and one calls a function in the
+other and vice versa, before the used function is defined, it won't work.
+Avoid using the autoload functionality at the toplevel.
+
+Hint: If you distribute a bunch of scripts you can pack them together with the
+|vimball| utility. Also read the user manual |distribute-script|.
+
+
+ vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 0c907bfb68..ee644be366 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -745,6 +745,7 @@ Cursor and mark position: *cursor-functions* *mark-functions*
screencol() get screen column of the cursor
screenrow() get screen row of the cursor
screenpos() screen row and col of a text character
+ virtcol2col() byte index of a text character on screen
getcurpos() get position of the cursor
getpos() get position of cursor, mark, etc.
setpos() set position of cursor, mark, etc.
@@ -872,6 +873,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..b013e00fe8 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -73,7 +73,7 @@ centralized reference of the differences.
- 'wildmenu' is enabled
- 'wildoptions' defaults to "pum,tagfile"
-- |man.vim| plugin is enabled, so |:Man| is available by default.
+- |man.lua| plugin is enabled, so |:Man| is available by default.
- |matchit| plugin is enabled. To disable it in your config: >
:let loaded_matchit = 1
@@ -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..6386e4ace1 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!
@@ -233,9 +235,16 @@ and 'winminwidth' are relevant.
*:vert* *:vertical*
:vert[ical] {cmd}
Execute {cmd}. If it contains a command that splits a window,
- it will be split vertically.
+ it will be split vertically. For `vertical wincmd =` windows
+ will be equalized only vertically.
Doesn't work for |:execute| and |:normal|.
+ *:hor* *:horizontal*
+:hor[izontal] {cmd}
+ Execute {cmd}. Currently only makes a difference for
+ `horizontal wincmd =`, which will equalize windows only
+ horizontally.
+
:lefta[bove] {cmd} *:lefta* *:leftabove*
:abo[veleft] {cmd} *:abo* *:aboveleft*
Execute {cmd}. If it contains a command that splits a window,
@@ -528,6 +537,10 @@ CTRL-W = Make all windows (almost) equally high and wide, but use
'winheight' and 'winwidth' for the current window.
Windows with 'winfixheight' set keep their height and windows
with 'winfixwidth' set keep their width.
+ To equalize only vertically (make window equally high) use
+ `vertical wincmd =`
+ To equalize only horizontally (make window equally wide) use
+ `horizontal wincmd =`
:res[ize] -N *:res* *:resize* *CTRL-W_-*
CTRL-W - Decrease current window height by N (default 1).
diff --git a/runtime/filetype.lua b/runtime/filetype.lua
index 9f5b5fd0dc..c50ba6453d 100644
--- a/runtime/filetype.lua
+++ b/runtime/filetype.lua
@@ -6,7 +6,7 @@ vim.g.did_load_filetypes = 1
vim.api.nvim_create_augroup('filetypedetect', { clear = false })
-vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, {
+vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile', 'StdinReadPost' }, {
group = 'filetypedetect',
callback = function(args)
local ft, on_detect = vim.filetype.match({ filename = args.match, buf = args.buf })
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 52a20d5c10..eda2cd555a 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -1,7 +1,7 @@
" Vim support file to detect file types
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2022 Jul 5
+" Last Change: 2022 Sep 09
" Only run this if enabled
if !exists("do_legacy_filetype")
@@ -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
@@ -718,9 +721,16 @@ au BufNewFile,BufRead *.git/worktrees/*/config.worktree setf gitconfig
au BufNewFile,BufRead .gitmodules,*.git/modules/*/config setf gitconfig
if !empty($XDG_CONFIG_HOME)
au BufNewFile,BufRead $XDG_CONFIG_HOME/git/config setf gitconfig
+ au BufNewFile,BufRead $XDG_CONFIG_HOME/git/attributes setf gitattributes
+ au BufNewFile,BufRead $XDG_CONFIG_HOME/git/ignore setf gitignore
endif
-au BufNewFile,BufRead git-rebase-todo setf gitrebase
-au BufRead,BufNewFile .gitsendemail.msg.?????? setf gitsendemail
+au BufNewFile,BufRead .gitattributes,*.git/info/attributes setf gitattributes
+au BufNewFile,BufRead */.config/git/attributes setf gitattributes
+au BufNewFile,BufRead */etc/gitattributes setf gitattributes
+au BufNewFile,BufRead .gitignore,*.git/info/exclude setf gitignore
+au BufNewFile,BufRead */.config/git/ignore setf gitignore
+au BufNewFile,BufRead git-rebase-todo setf gitrebase
+au BufRead,BufNewFile .gitsendemail.msg.?????? setf gitsendemail
au BufNewFile,BufRead *.git/*
\ if getline(1) =~# '^\x\{40,\}\>\|^ref: ' |
\ setf git |
@@ -865,11 +875,11 @@ au BufNewFile,BufRead *.htt,*.htb setf httest
" i3
au BufNewFile,BufRead */i3/config setf i3config
-au BufNewFile,BufRead */.i3/config setf i3config
+au BufNewFile,BufRead */.i3/config setf i3config
" sway
au BufNewFile,BufRead */sway/config setf swayconfig
-au BufNewFile,BufRead */.sway/config setf swayconfig
+au BufNewFile,BufRead */.sway/config setf swayconfig
" Icon
au BufNewFile,BufRead *.icn setf icon
@@ -938,7 +948,7 @@ au BufNewFile,BufRead *.java,*.jav setf java
au BufNewFile,BufRead *.jj,*.jjt setf javacc
" JavaScript, ECMAScript, ES module script, CommonJS script
-au BufNewFile,BufRead *.js,*.javascript,*.es,*.mjs,*.cjs setf javascript
+au BufNewFile,BufRead *.js,*.jsm,*.javascript,*.es,*.mjs,*.cjs setf javascript
" JavaScript with React
au BufNewFile,BufRead *.jsx setf javascriptreact
@@ -976,6 +986,9 @@ au BufNewFile,BufRead .babelrc,.eslintrc,.prettierrc,.firebaserc setf json
" JSONC
au BufNewFile,BufRead *.jsonc setf jsonc
+" Jsonnet
+au BufNewFile,BufRead *.jsonnet,*.libjsonnet setf jsonnet
+
" Julia
au BufNewFile,BufRead *.jl setf julia
@@ -1314,7 +1327,7 @@ au BufNewFile,BufRead *.or setf openroad
au BufNewFile,BufRead *.[Oo][Pp][Ll] setf opl
" OpenSCAD
-au BufNewFile,BufRead *.scad setf openscad
+au BufNewFile,BufRead *.scad setf openscad
" Oracle config file
au BufNewFile,BufRead *.ora setf ora
@@ -1389,7 +1402,8 @@ au BufNewFile,BufRead *.pod setf pod
" Also Phtml (was used for PHP 2 in the past).
" Also .ctp for Cake template file.
" Also .phpt for php tests.
-au BufNewFile,BufRead *.php,*.php\d,*.phtml,*.ctp,*.phpt setf php
+" Also .theme for Drupal theme files.
+au BufNewFile,BufRead *.php,*.php\d,*.phtml,*.ctp,*.phpt,*.theme setf php
" PHP config
au BufNewFile,BufRead php.ini-* setf dosini
@@ -1710,6 +1724,9 @@ au BufNewFile,BufRead *.sdl,*.pr setf sdl
" sed
au BufNewFile,BufRead *.sed setf sed
+" SubRip
+au BufNewFile,BufRead *.srt setf srt
+
" svelte
au BufNewFile,BufRead *.svelte setf svelte
@@ -1820,7 +1837,7 @@ au BufNewFile,BufRead *.score setf slrnsc
au BufNewFile,BufRead *.st setf st
" Smalltalk (and Rexx, TeX, and Visual Basic)
-au BufNewFile,BufRead *.cls call dist#ft#FTcls()
+au BufNewFile,BufRead *.cls call dist#ft#FTcls()
" Smarty templates
au BufNewFile,BufRead *.tpl setf smarty
@@ -1927,8 +1944,8 @@ au BufNewFile,BufRead *.cm setf voscm
au BufNewFile,BufRead *.swift setf swift
au BufNewFile,BufRead *.swift.gyb setf swiftgyb
-" Swift Intermediate Language
-au BufNewFile,BufRead *.sil setf sil
+" Swift Intermediate Language or SILE
+au BufNewFile,BufRead *.sil call dist#ft#FTsil()
" Sysctl
au BufNewFile,BufRead */etc/sysctl.conf,*/etc/sysctl.d/*.conf setf sysctl
@@ -2095,6 +2112,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
@@ -2564,6 +2586,9 @@ au BufNewFile,BufRead *.txt
\| setf text
\| endif
+" Blueprint markup files
+au BufNewFile,BufRead *.blp setf blueprint
+
if !exists('g:did_load_ftdetect')
" Use the filetype detect plugins. They may overrule any of the previously
" detected filetypes.
diff --git a/runtime/ftplugin/gitattributes.vim b/runtime/ftplugin/gitattributes.vim
new file mode 100644
index 0000000000..2025d009d2
--- /dev/null
+++ b/runtime/ftplugin/gitattributes.vim
@@ -0,0 +1,13 @@
+" Vim filetype plugin
+" Language: git attributes
+" Maintainer: ObserverOfTime <chronobserver@disroot.org>
+" Last Change: 2022 Sep 08
+
+if exists('b:did_ftplugin')
+ finish
+endif
+let b:did_ftplugin = 1
+
+setl comments=:# commentstring=#\ %s
+
+let b:undo_ftplugin = 'setl com< cms<'
diff --git a/runtime/ftplugin/gitignore.vim b/runtime/ftplugin/gitignore.vim
new file mode 100644
index 0000000000..3502dd2717
--- /dev/null
+++ b/runtime/ftplugin/gitignore.vim
@@ -0,0 +1,13 @@
+" Vim filetype plugin
+" Language: git ignore
+" Maintainer: ObserverOfTime <chronobserver@disroot.org>
+" Last Change: 2022 Sep 10
+
+if exists('b:did_ftplugin')
+ finish
+endif
+let b:did_ftplugin = 1
+
+setl comments=:# commentstring=#\ %s
+
+let b:undo_ftplugin = 'setl com< cms<'
diff --git a/runtime/ftplugin/jsonnet.vim b/runtime/ftplugin/jsonnet.vim
new file mode 100644
index 0000000000..1e621e1867
--- /dev/null
+++ b/runtime/ftplugin/jsonnet.vim
@@ -0,0 +1,17 @@
+" Vim filetype plugin
+" Language: Jsonnet
+" Maintainer: Cezary Drożak <cezary@drozak.net>
+" URL: https://github.com/google/vim-jsonnet
+" Last Change: 2022-09-08
+
+" Only do this when not done yet for this buffer
+if exists("b:did_ftplugin")
+ finish
+endif
+
+" Don't load another plugin for this buffer
+let b:did_ftplugin = 1
+
+setlocal commentstring=//\ %s
+
+let b:undo_ftplugin = "setlocal commentstring<"
diff --git a/runtime/ftplugin/lua.lua b/runtime/ftplugin/lua.lua
new file mode 100644
index 0000000000..415cf28f9a
--- /dev/null
+++ b/runtime/ftplugin/lua.lua
@@ -0,0 +1,3 @@
+if vim.g.ts_highlight_lua then
+ vim.treesitter.start()
+end
diff --git a/runtime/ftplugin/lua.vim b/runtime/ftplugin/lua.vim
index 2604257594..aaa61f71d9 100644
--- a/runtime/ftplugin/lua.vim
+++ b/runtime/ftplugin/lua.vim
@@ -1,46 +1,46 @@
" Vim filetype plugin file.
-" Language: Lua
+" Language: Lua
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Max Ischenko <mfi@ukr.net>
-" Last Change: 2021 Nov 15
+" Contributor: Dorai Sitaram <ds26@gte.com>
+" Last Change: 2022 Sep 05
-" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
finish
endif
-
-" Don't load another plugin for this buffer
let b:did_ftplugin = 1
let s:cpo_save = &cpo
set cpo&vim
-" Set 'formatoptions' to break comment lines but not other lines, and insert
-" the comment leader when hitting <CR> or using "o".
+setlocal comments=:--
+setlocal commentstring=--\ %s
setlocal formatoptions-=t formatoptions+=croql
-setlocal comments=:--
-setlocal commentstring=--%s
+let &l:define = '\<function\|\<local\%(\s\+function\)\='
+
setlocal suffixesadd=.lua
-let b:undo_ftplugin = "setlocal fo< com< cms< sua<"
+let b:undo_ftplugin = "setlocal cms< com< def< fo< sua<"
if exists("loaded_matchit") && !exists("b:match_words")
let b:match_ignorecase = 0
let b:match_words =
- \ '\<\%(do\|function\|if\)\>:' .
- \ '\<\%(return\|else\|elseif\)\>:' .
- \ '\<end\>,' .
- \ '\<repeat\>:\<until\>,' .
- \ '\%(--\)\=\[\(=*\)\[:]\1]'
- let b:undo_ftplugin .= " | unlet! b:match_words b:match_ignorecase"
+ \ '\<\%(do\|function\|if\)\>:' ..
+ \ '\<\%(return\|else\|elseif\)\>:' ..
+ \ '\<end\>,' ..
+ \ '\<repeat\>:\<until\>,' ..
+ \ '\%(--\)\=\[\(=*\)\[:]\1]'
+ let b:undo_ftplugin ..= " | unlet! b:match_words b:match_ignorecase"
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Lua Source Files (*.lua)\t*.lua\n" .
- \ "All Files (*.*)\t*.*\n"
- let b:undo_ftplugin .= " | unlet! b:browsefilter"
+ let b:browsefilter = "Lua Source Files (*.lua)\t*.lua\n" ..
+ \ "All Files (*.*)\t*.*\n"
+ let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
let &cpo = s:cpo_save
unlet s:cpo_save
+
+" vim: nowrap sw=2 sts=2 ts=8 noet:
diff --git a/runtime/ftplugin/lynx.vim b/runtime/ftplugin/lynx.vim
new file mode 100644
index 0000000000..b76c69f0ae
--- /dev/null
+++ b/runtime/ftplugin/lynx.vim
@@ -0,0 +1,29 @@
+" Vim filetype plugin file
+" Language: Lynx Web Browser Configuration
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Last Change: 2022 Sep 09
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+setlocal comments=:#
+setlocal commentstring=#\ %s
+setlocal formatoptions-=t formatoptions+=croql
+
+let b:undo_ftplugin = "setl cms< com< fo<"
+
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "Lynx Configuration Files (lynx.cfg .lynxrc)\tlynx.cfg;.lynxrc\n" ..
+ \ "All Files (*.*)\t*.*\n"
+ let b:undo_ftplugin ..= " | unlet! b:browsefilter"
+endif
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
+
+" vim: nowrap sw=2 sts=2 ts=8 noet:
diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim
index d7a08a9941..277ce3c0b3 100644
--- a/runtime/ftplugin/man.vim
+++ b/runtime/ftplugin/man.vim
@@ -17,12 +17,12 @@ setlocal iskeyword=@-@,:,a-z,A-Z,48-57,_,.,-,(,)
setlocal nonumber norelativenumber
setlocal foldcolumn=0 colorcolumn=0 nolist nofoldenable
-setlocal tagfunc=man#goto_tag
+setlocal tagfunc=v:lua.require'man'.goto_tag
if !exists('g:no_plugin_maps') && !exists('g:no_man_maps')
nnoremap <silent> <buffer> j gj
nnoremap <silent> <buffer> k gk
- nnoremap <silent> <buffer> gO :call man#show_toc()<CR>
+ nnoremap <silent> <buffer> gO :lua require'man'.show_toc()<CR>
nnoremap <silent> <buffer> <2-LeftMouse> :Man<CR>
if get(b:, 'pager')
nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>q
diff --git a/runtime/ftplugin/racket.vim b/runtime/ftplugin/racket.vim
new file mode 100644
index 0000000000..3aa413397e
--- /dev/null
+++ b/runtime/ftplugin/racket.vim
@@ -0,0 +1,82 @@
+" Vim filetype plugin
+" Language: Racket
+" Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com>
+" Previous Maintainer: Will Langstroth <will@langstroth.com>
+" URL: https://github.com/benknoble/vim-racket
+" Last Change: 2022 Aug 29
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+" quick hack to allow adding values
+setlocal iskeyword=@,!,#-',*-:,<-Z,a-z,~,_,94
+
+" Enable auto begin new comment line when continuing from an old comment line
+setlocal comments=:;;;;,:;;;,:;;,:;
+setlocal formatoptions+=r
+
+"setlocal commentstring=;;%s
+setlocal commentstring=#\|\ %s\ \|#
+
+setlocal formatprg=raco\ fmt
+
+" Undo our settings when the filetype changes away from Racket
+" (this should be amended if settings/mappings are added above!)
+let b:undo_ftplugin =
+ \ "setlocal iskeyword< lispwords< lisp< comments< formatoptions< formatprg<"
+ \. " | setlocal commentstring<"
+
+if !exists("no_plugin_maps") && !exists("no_racket_maps")
+ " Simply setting keywordprg like this works:
+ " setlocal keywordprg=raco\ docs
+ " but then vim says:
+ " "press ENTER or type a command to continue"
+ " We avoid the annoyance of having to hit enter by remapping K directly.
+ function s:RacketDoc(word) abort
+ execute 'silent !raco docs --' shellescape(a:word)
+ redraw!
+ endfunction
+ nnoremap <buffer> <Plug>RacketDoc :call <SID>RacketDoc(expand('<cword>'))<CR>
+ nmap <buffer> K <Plug>RacketDoc
+
+ " For the visual mode K mapping, it's slightly more convoluted to get the
+ " selected text:
+ function! s:Racket_visual_doc()
+ try
+ let l:old_a = @a
+ normal! gv"ay
+ call system("raco docs '". @a . "'")
+ redraw!
+ return @a
+ finally
+ let @a = l:old_a
+ endtry
+ endfunction
+
+ xnoremap <buffer> <Plug>RacketDoc :call <SID>Racket_visual_doc()<cr>
+ xmap <buffer> K <Plug>RacketDoc
+
+ let b:undo_ftplugin .=
+ \ " | silent! execute 'nunmap <buffer> K'"
+ \. " | silent! execute 'xunmap <buffer> K'"
+endif
+
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter =
+ \ "Racket Source Files (*.rkt *.rktl)\t*.rkt;*.rktl\n"
+ \. "All Files (*.*)\t*.*\n"
+ let b:undo_ftplugin .= " | unlet! b:browsefilter"
+endif
+
+if exists("loaded_matchit") && !exists("b:match_words")
+ let b:match_words = '#|:|#'
+ let b:undo_ftplugin .= " | unlet! b:match_words"
+endif
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/ftplugin/sh.vim b/runtime/ftplugin/sh.vim
index 93a46f63e2..b6fdb8f3e2 100644
--- a/runtime/ftplugin/sh.vim
+++ b/runtime/ftplugin/sh.vim
@@ -1,12 +1,12 @@
" Vim filetype plugin file
-" Language: sh
-"
-" This runtime file is looking for a new maintainer.
-"
-" Former maintainer: Dan Sharp
-" Last Changed: 20 Jan 2009
-
-if exists("b:did_ftplugin") | finish | endif
+" Language: sh
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Dan Sharp
+" Last Change: 2022 Sep 07
+
+if exists("b:did_ftplugin")
+ finish
+endif
let b:did_ftplugin = 1
" Make sure the continuation lines below do not cause problems in
@@ -14,28 +14,35 @@ let b:did_ftplugin = 1
let s:save_cpo = &cpo
set cpo-=C
-setlocal commentstring=#%s
+setlocal comments=:#
+setlocal commentstring=#\ %s
+setlocal formatoptions-=t formatoptions+=croql
+
+let b:undo_ftplugin = "setl com< cms< fo<"
" Shell: thanks to Johannes Zellner
-if exists("loaded_matchit")
- let s:sol = '\%(;\s*\|^\s*\)\@<=' " start of line
- let b:match_words =
- \ s:sol.'if\>:' . s:sol.'elif\>:' . s:sol.'else\>:' . s:sol. 'fi\>,' .
- \ s:sol.'\%(for\|while\)\>:' . s:sol. 'done\>,' .
- \ s:sol.'case\>:' . s:sol. 'esac\>'
+if exists("loaded_matchit") && !exists("b:match_words")
+ let b:match_ignorecase = 0
+ let s:sol = '\%(;\s*\|^\s*\)\@<=' " start of line
+ let b:match_words =
+ \ s:sol .. 'if\>:' .. s:sol.'elif\>:' .. s:sol.'else\>:' .. s:sol .. 'fi\>,' ..
+ \ s:sol .. '\%(for\|while\)\>:' .. s:sol .. 'done\>,' ..
+ \ s:sol .. 'case\>:' .. s:sol .. 'esac\>'
+ unlet s:sol
+ let b:undo_ftplugin ..= " | unlet! b:match_ignorecase b:match_words"
endif
" Change the :browse e filter to primarily show shell-related files.
-if has("gui_win32")
- let b:browsefilter="Bourne Shell Scripts (*.sh)\t*.sh\n" .
- \ "Korn Shell Scripts (*.ksh)\t*.ksh\n" .
- \ "Bash Shell Scripts (*.bash)\t*.bash\n" .
- \ "All Files (*.*)\t*.*\n"
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "Bourne Shell Scripts (*.sh)\t*.sh\n" ..
+ \ "Korn Shell Scripts (*.ksh)\t*.ksh\n" ..
+ \ "Bash Shell Scripts (*.bash)\t*.bash\n" ..
+ \ "All Files (*.*)\t*.*\n"
+ let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
-" Undo the stuff we changed.
-let b:undo_ftplugin = "setlocal cms< | unlet! b:browsefilter b:match_words"
-
" Restore the saved compatibility options.
let &cpo = s:save_cpo
unlet s:save_cpo
+
+" vim: nowrap sw=2 sts=2 ts=8 noet:
diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim
index 772899cb42..82a4b13f9f 100644
--- a/runtime/ftplugin/vim.vim
+++ b/runtime/ftplugin/vim.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin
" Language: Vim
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2022 Aug 4
+" Last Change: 2022 Sep 09
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
diff --git a/runtime/ftplugin/zimbu.vim b/runtime/ftplugin/zimbu.vim
index e365ccf07e..cbe2f55572 100644
--- a/runtime/ftplugin/zimbu.vim
+++ b/runtime/ftplugin/zimbu.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Zimbu
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2021 Nov 12
+" Last Change: 2022 Sep 07
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -28,7 +28,7 @@ endif
" Set 'comments' to format dashed lists in comments.
" And to keep Zudocu comment characters.
-setlocal comments=sO:#\ -,mO:#\ \ ,:#=,:#-,:#%,:#
+setlocal comments=sO:#\ -,mO:#\ \ ,exO:#/,s:/*,m:\ ,ex:*/,:#=,:#-,:#%,:#
setlocal errorformat^=%f\ line\ %l\ col\ %c:\ %m,ERROR:\ %m
diff --git a/runtime/ftplugin/zsh.vim b/runtime/ftplugin/zsh.vim
index 34410f1c62..0ca8077305 100644
--- a/runtime/ftplugin/zsh.vim
+++ b/runtime/ftplugin/zsh.vim
@@ -2,7 +2,7 @@
" Language: Zsh shell script
" Maintainer: Christian Brabandt <cb@256bit.org>
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2020-09-01
+" Latest Revision: 2021-04-03
" License: Vim (see :h license)
" Repository: https://github.com/chrisbra/vim-zsh
diff --git a/runtime/indent/json.vim b/runtime/indent/json.vim
index 09c7d7a85a..510f7e8f42 100644
--- a/runtime/indent/json.vim
+++ b/runtime/indent/json.vim
@@ -3,6 +3,7 @@
" Maintainer: Eli Parra <eli@elzr.com> https://github.com/elzr/vim-json
" Last Change: 2020 Aug 30
" https://github.com/jakar/vim-json/commit/20b650e22aa750c4ab6a66aa646bdd95d7cd548a#diff-e81fc111b2052e306d126bd9989f7b7c
+" 2022 Sep 07: b:undo_indent added by Doug Kearns
" Original Author: Rogerz Zhang <rogerz.zhang at gmail.com> http://github.com/rogerz/vim-json
" Acknowledgement: Based off of vim-javascript maintained by Darrick Wiebe
" http://www.vim.org/scripts/script.php?script_id=2765
@@ -22,6 +23,8 @@ setlocal nosmartindent
setlocal indentexpr=GetJSONIndent(v:lnum)
setlocal indentkeys=0{,0},0),0[,0],!^F,o,O,e
+let b:undo_indent = "setl inde< indk< si<"
+
" Only define the function once.
if exists("*GetJSONIndent")
finish
diff --git a/runtime/indent/racket.vim b/runtime/indent/racket.vim
new file mode 100644
index 0000000000..93bd38fbff
--- /dev/null
+++ b/runtime/indent/racket.vim
@@ -0,0 +1,60 @@
+" Vim indent file
+" Language: Racket
+" Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com>
+" Previous Maintainer: Will Langstroth <will@langstroth.com>
+" URL: https://github.com/benknoble/vim-racket
+" Last Change: 2022 Aug 12
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal lisp autoindent nosmartindent
+
+setlocal lispwords+=module,module*,module+,parameterize,let-values,let*-values,letrec-values,local
+setlocal lispwords+=define/contract
+setlocal lispwords+=λ
+setlocal lispwords+=with-handlers
+setlocal lispwords+=define-values,opt-lambda,case-lambda,syntax-rules,with-syntax,syntax-case,syntax-parse
+setlocal lispwords+=define-for-syntax,define-syntax-parser,define-syntax-parse-rule,define-syntax-class,define-splicing-syntax-class
+setlocal lispwords+=define-signature,unit,unit/sig,compund-unit/sig,define-values/invoke-unit/sig
+setlocal lispwords+=define-opt/c,define-syntax-rule
+setlocal lispwords+=define-test-suite
+setlocal lispwords+=struct
+setlocal lispwords+=with-input-from-file,with-output-to-file
+
+" Racket OOP
+" TODO missing a lot of define-like forms here (e.g., define/augment, etc.)
+setlocal lispwords+=class,class*,mixin,interface,class/derived
+setlocal lispwords+=define/public,define/pubment,define/public-final
+setlocal lispwords+=define/override,define/overment,define/override-final
+setlocal lispwords+=define/augment,define/augride,define/augment-final
+setlocal lispwords+=define/private
+
+" kanren
+setlocal lispwords+=fresh,run,run*,project,conde,condu
+
+" loops
+setlocal lispwords+=for,for/list,for/fold,for*,for*/list,for*/fold,for/or,for/and,for*/or,for*/and
+setlocal lispwords+=for/hash,for/hasheq,for/hasheqv,for/sum,for/flvector,for*/flvector,for/vector,for*/vector,for*/sum,for*/hash,for*/hasheq,for*/hasheqv
+setlocal lispwords+=for/async
+setlocal lispwords+=for/set,for*/set
+setlocal lispwords+=for/first,for*/first
+
+setlocal lispwords+=match,match*,match/values,define/match,match-lambda,match-lambda*,match-lambda**
+setlocal lispwords+=match-let,match-let*,match-let-values,match-let*-values
+setlocal lispwords+=match-letrec,match-define,match-define-values
+
+setlocal lispwords+=let/cc,let/ec
+
+" qi
+setlocal lispwords+=define-flow,define-switch,flow-lambda,switch-lambda,on,switch,π,λ01
+setlocal lispwords+=define-qi-syntax,define-qi-syntax-parser,define-qi-syntax-rule
+
+" gui-easy
+setlocal lispwords+=if-view,case-view,cond-view,list-view,dyn-view
+setlocal lispwords+=case/dep
+setlocal lispwords+=define/obs
+
+let b:undo_indent = "setlocal lisp< ai< si< lw<"
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/indent/testdir/runtest.vim b/runtime/indent/testdir/runtest.vim
index 6bbd33cacd..fa4e16e381 100644
--- a/runtime/indent/testdir/runtest.vim
+++ b/runtime/indent/testdir/runtest.vim
@@ -11,6 +11,7 @@ syn on
set nowrapscan
set report=9999
set modeline
+set debug=throw
au! SwapExists * call HandleSwapExists()
func HandleSwapExists()
@@ -84,7 +85,12 @@ for fname in glob('testdir/*.in', 1, 1)
exe start + 1
if pattern == ''
- exe 'normal =' . (end - 1) . 'G'
+ try
+ exe 'normal =' . (end - 1) . 'G'
+ catch
+ call append(indent_at, 'ERROR: ' . v:exception)
+ let failed = 1
+ endtry
else
let lnum = search(pattern)
if lnum <= 0
@@ -99,7 +105,12 @@ for fname in glob('testdir/*.in', 1, 1)
else
exe lnum - 1
endif
- normal ==
+ try
+ normal ==
+ catch
+ call append(indent_at, 'ERROR: ' . v:exception)
+ let failed = 1
+ endtry
endif
endif
endwhile
diff --git a/runtime/indent/testdir/vim.in b/runtime/indent/testdir/vim.in
index 873045bc2c..5eb262f50a 100644
--- a/runtime/indent/testdir/vim.in
+++ b/runtime/indent/testdir/vim.in
@@ -36,6 +36,13 @@ let t = [
\ },
\ ]
+def Func()
+ var d = dd
+ ->extend({
+ })
+ eval 0
+enddef
+
" END_INDENT
" START_INDENT
diff --git a/runtime/indent/testdir/vim.ok b/runtime/indent/testdir/vim.ok
index 8e70abe619..932eebef43 100644
--- a/runtime/indent/testdir/vim.ok
+++ b/runtime/indent/testdir/vim.ok
@@ -36,6 +36,13 @@ let t = [
\ },
\ ]
+def Func()
+ var d = dd
+ ->extend({
+ })
+ eval 0
+enddef
+
" END_INDENT
" START_INDENT
diff --git a/runtime/indent/vim.vim b/runtime/indent/vim.vim
index 8076b2df07..3beb70d255 100644
--- a/runtime/indent/vim.vim
+++ b/runtime/indent/vim.vim
@@ -33,7 +33,9 @@ function GetVimIndent()
endtry
endfunc
-let s:lineContPat = '^\s*\(\\\|"\\ \)'
+" Legacy script line continuation and Vim9 script operators that must mean an
+" expression that continues from the previous line.
+let s:lineContPat = '^\s*\(\\\|"\\ \|->\)'
function GetVimIndentIntern()
" If the current line has line continuation and the previous one too, use
@@ -133,15 +135,15 @@ function GetVimIndentIntern()
endif
endif
- " For a line starting with "}" find the matching "{". If it is at the start
- " of the line align with it, probably end of a block.
+ " For a line starting with "}" find the matching "{". Align with that line,
+ " it is either the matching block start or dictionary start.
" Use the mapped "%" from matchit to find the match, otherwise we may match
" a { inside a comment or string.
if cur_text =~ '^\s*}'
if maparg('%') != ''
exe v:lnum
silent! normal %
- if line('.') < v:lnum && getline('.') =~ '^\s*{'
+ if line('.') < v:lnum
let ind = indent('.')
endif
else
@@ -149,19 +151,33 @@ function GetVimIndentIntern()
endif
endif
- " Below a line starting with "}" find the matching "{". If it is at the
- " end of the line we must be below the end of a dictionary.
- if prev_text =~ '^\s*}'
- if maparg('%') != ''
- exe lnum
- silent! normal %
- if line('.') == lnum || getline('.') !~ '^\s*{'
- let ind = ind - shiftwidth()
+ " Look back for a line to align with
+ while lnum > 1
+ " Below a line starting with "}" find the matching "{".
+ if prev_text =~ '^\s*}'
+ if maparg('%') != ''
+ exe lnum
+ silent! normal %
+ if line('.') < lnum
+ let lnum = line('.')
+ let ind = indent(lnum)
+ let prev_text = getline(lnum)
+ else
+ break
+ endif
+ else
+ " todo: use searchpair() to find a match
+ break
endif
+ elseif prev_text =~ s:lineContPat
+ " looks like a continuation like, go back one line
+ let lnum = lnum - 1
+ let ind = indent(lnum)
+ let prev_text = getline(lnum)
else
- " todo: use searchpair() to find a match
+ break
endif
- endif
+ endwhile
" Below a line starting with "]" we must be below the end of a list.
" Include a "}" and "},} in case a dictionary ends too.
diff --git a/runtime/indent/yaml.vim b/runtime/indent/yaml.vim
index d732c37c05..93fd8ea6f6 100644
--- a/runtime/indent/yaml.vim
+++ b/runtime/indent/yaml.vim
@@ -1,7 +1,7 @@
" Vim indent file
" Language: YAML
" Maintainer: Nikolai Pavlov <zyx.vim@gmail.com>
-" Last Update: Lukas Reineke
+" Last Updates: Lukas Reineke, "lacygoill"
" Last Change: 2022 Jun 17
" Only load this indent file when no other was loaded.
@@ -29,8 +29,8 @@ function s:FindPrevLessIndentedLine(lnum, ...)
let prevlnum = prevnonblank(a:lnum-1)
let curindent = a:0 ? a:1 : indent(a:lnum)
while prevlnum
- \&& indent(prevlnum) >= curindent
- \&& getline(prevlnum) !~# '^\s*#'
+ \ && indent(prevlnum) >= curindent
+ \ && getline(prevlnum) !~# '^\s*#'
let prevlnum = prevnonblank(prevlnum-1)
endwhile
return prevlnum
@@ -54,7 +54,7 @@ let s:c_ns_anchor_name = s:c_ns_anchor_char .. '+'
let s:c_ns_anchor_property = '\v\&' .. s:c_ns_anchor_name
let s:ns_word_char = '\v[[:alnum:]_\-]'
-let s:ns_tag_char = '\v%(%\x\x|' .. s:ns_word_char .. '|[#/;?:@&=+$.~*''()])'
+let s:ns_tag_char = '\v%(\x\x|' .. s:ns_word_char .. '|[#/;?:@&=+$.~*''()])'
let s:c_named_tag_handle = '\v\!' .. s:ns_word_char .. '+\!'
let s:c_secondary_tag_handle = '\v\!\!'
let s:c_primary_tag_handle = '\v\!'
@@ -63,7 +63,7 @@ let s:c_tag_handle = '\v%(' .. s:c_named_tag_handle.
\ '|' .. s:c_primary_tag_handle .. ')'
let s:c_ns_shorthand_tag = '\v' .. s:c_tag_handle .. s:ns_tag_char .. '+'
let s:c_non_specific_tag = '\v\!'
-let s:ns_uri_char = '\v%(%\x\x|' .. s:ns_word_char .. '\v|[#/;?:@&=+$,.!~*''()[\]])'
+let s:ns_uri_char = '\v%(\x\x|' .. s:ns_word_char .. '\v|[#/;?:@&=+$,.!~*''()[\]])'
let s:c_verbatim_tag = '\v\!\<' .. s:ns_uri_char.. '+\>'
let s:c_ns_tag_property = '\v' .. s:c_verbatim_tag.
\ '\v|' .. s:c_ns_shorthand_tag.
diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua
index 5da3d2a92f..82ed0305f7 100644
--- a/runtime/lua/man.lua
+++ b/runtime/lua/man.lua
@@ -1,7 +1,75 @@
require('vim.compat')
+local api, fn = vim.api, vim.fn
+
+local find_arg = '-w'
+local localfile_arg = true -- Always use -l if possible. #6683
local buf_hls = {}
+local M = {}
+
+local function man_error(msg)
+ M.errormsg = 'man.lua: ' .. vim.inspect(msg)
+ error(M.errormsg)
+end
+
+-- Run a system command and timeout after 30 seconds.
+local function man_system(cmd, silent)
+ local stdout_data = {}
+ local stderr_data = {}
+ local stdout = vim.loop.new_pipe(false)
+ local stderr = vim.loop.new_pipe(false)
+
+ local done = false
+ local exit_code
+
+ local handle = vim.loop.spawn(cmd[1], {
+ args = vim.list_slice(cmd, 2),
+ stdio = { nil, stdout, stderr },
+ }, function(code)
+ exit_code = code
+ stdout:close()
+ stderr:close()
+ done = true
+ end)
+
+ if handle then
+ stdout:read_start(function(_, data)
+ stdout_data[#stdout_data + 1] = data
+ end)
+ stderr:read_start(function(_, data)
+ stderr_data[#stderr_data + 1] = data
+ end)
+ else
+ stdout:close()
+ stderr:close()
+ if not silent then
+ man_error(string.format('command error: %s', table.concat(cmd)))
+ end
+ end
+
+ vim.wait(30000, function()
+ return done
+ end)
+
+ if not done then
+ if handle then
+ vim.loop.shutdown(handle)
+ stdout:close()
+ stderr:close()
+ end
+ man_error(string.format('command timed out: %s', table.concat(cmd, ' ')))
+ end
+
+ if exit_code ~= 0 and not silent then
+ man_error(
+ string.format("command error '%s': %s", table.concat(cmd, ' '), table.concat(stderr_data))
+ )
+ end
+
+ return table.concat(stdout_data)
+end
+
local function highlight_line(line, linenr)
local chars = {}
local prev_char = ''
@@ -152,21 +220,540 @@ local function highlight_line(line, linenr)
end
local function highlight_man_page()
- local mod = vim.api.nvim_buf_get_option(0, 'modifiable')
- vim.api.nvim_buf_set_option(0, 'modifiable', true)
+ local mod = vim.bo.modifiable
+ vim.bo.modifiable = true
- local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
+ local lines = api.nvim_buf_get_lines(0, 0, -1, false)
for i, line in ipairs(lines) do
lines[i] = highlight_line(line, i)
end
- vim.api.nvim_buf_set_lines(0, 0, -1, false, lines)
+ api.nvim_buf_set_lines(0, 0, -1, false, lines)
for _, args in ipairs(buf_hls) do
- vim.api.nvim_buf_add_highlight(unpack(args))
+ api.nvim_buf_add_highlight(unpack(args))
end
buf_hls = {}
- vim.api.nvim_buf_set_option(0, 'modifiable', mod)
+ vim.bo.modifiable = mod
+end
+
+-- replace spaces in a man page name with underscores
+-- intended for PostgreSQL, which has man pages like 'CREATE_TABLE(7)';
+-- while editing SQL source code, it's nice to visually select 'CREATE TABLE'
+-- and hit 'K', which requires this transformation
+local function spaces_to_underscores(str)
+ local res = str:gsub('%s', '_')
+ return res
+end
+
+local function get_path(sect, name, silent)
+ name = name or ''
+ sect = sect or ''
+ -- Some man implementations (OpenBSD) return all available paths from the
+ -- search command. Previously, this function would simply select the first one.
+ --
+ -- However, some searches will report matches that are incorrect:
+ -- man -w strlen may return string.3 followed by strlen.3, and therefore
+ -- selecting the first would get us the wrong page. Thus, we must find the
+ -- first matching one.
+ --
+ -- There's yet another special case here. Consider the following:
+ -- If you run man -w strlen and string.3 comes up first, this is a problem. We
+ -- should search for a matching named one in the results list.
+ -- However, if you search for man -w clock_gettime, you will *only* get
+ -- clock_getres.2, which is the right page. Searching the resuls for
+ -- clock_gettime will no longer work. In this case, we should just use the
+ -- first one that was found in the correct section.
+ --
+ -- Finally, we can avoid relying on -S or -s here since they are very
+ -- inconsistently supported. Instead, call -w with a section and a name.
+ local cmd
+ if sect == '' then
+ cmd = { 'man', find_arg, name }
+ else
+ cmd = { 'man', find_arg, sect, name }
+ end
+
+ local lines = man_system(cmd, silent)
+ if lines == nil then
+ return nil
+ end
+
+ local results = vim.split(lines, '\n', { trimempty = true })
+
+ if #results == 0 then
+ return
+ end
+
+ -- find any that match the specified name
+ local namematches = vim.tbl_filter(function(v)
+ return fn.fnamemodify(v, ':t'):match(name)
+ end, results) or {}
+ local sectmatches = {}
+
+ if #namematches > 0 and sect ~= '' then
+ sectmatches = vim.tbl_filter(function(v)
+ return fn.fnamemodify(v, ':e') == sect
+ end, namematches)
+ end
+
+ return fn.substitute(sectmatches[1] or namematches[1] or results[1], [[\n\+$]], '', '')
+end
+
+local function matchstr(text, pat_or_re)
+ local re = type(pat_or_re) == 'string' and vim.regex(pat_or_re) or pat_or_re
+
+ local s, e = re:match_str(text)
+
+ if s == nil then
+ return
+ end
+
+ return text:sub(vim.str_utfindex(text, s) + 1, vim.str_utfindex(text, e))
+end
+
+-- attempt to extract the name and sect out of 'name(sect)'
+-- otherwise just return the largest string of valid characters in ref
+local function extract_sect_and_name_ref(ref)
+ ref = ref or ''
+ if ref:sub(1, 1) == '-' then -- try ':Man -pandoc' with this disabled.
+ man_error("manpage name cannot start with '-'")
+ end
+ local ref1 = ref:match('[^()]+%([^()]+%)')
+ if not ref1 then
+ local name = ref:match('[^()]+')
+ if not name then
+ man_error('manpage reference cannot contain only parentheses: ' .. ref)
+ end
+ return '', spaces_to_underscores(name)
+ end
+ local parts = vim.split(ref1, '(', { plain = true })
+ -- see ':Man 3X curses' on why tolower.
+ -- TODO(nhooyr) Not sure if this is portable across OSs
+ -- but I have not seen a single uppercase section.
+ local sect = vim.split(parts[2] or '', ')', { plain = true })[1]:lower()
+ local name = spaces_to_underscores(parts[1])
+ return sect, name
+end
+
+-- verify_exists attempts to find the path to a manpage
+-- based on the passed section and name.
+--
+-- 1. If manpage could not be found with the given sect and name,
+-- then try all the sections in b:man_default_sects.
+-- 2. If it still could not be found, then we try again without a section.
+-- 3. If still not found but $MANSECT is set, then we try again with $MANSECT
+-- unset.
+local function verify_exists(sect, name)
+ if sect and sect ~= '' then
+ local ret = get_path(sect, name, true)
+ if ret then
+ return ret
+ end
+ end
+
+ if vim.b.man_default_sects ~= nil then
+ local sects = vim.split(vim.b.man_default_sects, ',', { plain = true, trimempty = true })
+ for _, sec in ipairs(sects) do
+ local ret = get_path(sec, name, true)
+ if ret then
+ return ret
+ end
+ end
+ end
+
+ -- if none of the above worked, we will try with no section
+ local res_empty_sect = get_path('', name, true)
+ if res_empty_sect then
+ return res_empty_sect
+ end
+
+ -- if that still didn't work, we will check for $MANSECT and try again with it
+ -- unset
+ if vim.env.MANSECT then
+ local mansect = vim.env.MANSECT
+ vim.env.MANSECT = nil
+ local res = get_path('', name, true)
+ vim.env.MANSECT = mansect
+ if res then
+ return res
+ end
+ end
+
+ -- finally, if that didn't work, there is no hope
+ man_error('no manual entry for ' .. name)
+end
+
+local EXT_RE = vim.regex([[\.\%([glx]z\|bz2\|lzma\|Z\)$]])
+
+-- Extracts the name/section from the 'path/name.sect', because sometimes the actual section is
+-- more specific than what we provided to `man` (try `:Man 3 App::CLI`).
+-- Also on linux, name seems to be case-insensitive. So for `:Man PRIntf`, we
+-- still want the name of the buffer to be 'printf'.
+local function extract_sect_and_name_path(path)
+ local tail = fn.fnamemodify(path, ':t')
+ if EXT_RE:match_str(path) then -- valid extensions
+ tail = fn.fnamemodify(tail, ':r')
+ end
+ local name, sect = tail:match('^(.+)%.([^.]+)$')
+ return sect, name
+end
+
+local function find_man()
+ local win = 1
+ while win <= fn.winnr('$') do
+ local buf = fn.winbufnr(win)
+ if vim.bo[buf].filetype == 'man' then
+ vim.cmd(win .. 'wincmd w')
+ return true
+ end
+ win = win + 1
+ end
+ return false
+end
+
+local function set_options(pager)
+ vim.bo.swapfile = false
+ vim.bo.buftype = 'nofile'
+ vim.bo.bufhidden = 'hide'
+ vim.bo.modified = false
+ vim.bo.readonly = true
+ vim.bo.modifiable = false
+ vim.b.pager = pager
+ vim.bo.filetype = 'man'
+end
+
+local function get_page(path, silent)
+ -- Disable hard-wrap by using a big $MANWIDTH (max 1000 on some systems #9065).
+ -- Soft-wrap: ftplugin/man.lua sets wrap/breakindent/….
+ -- Hard-wrap: driven by `man`.
+ local manwidth
+ if (vim.g.man_hardwrap or 1) ~= 1 then
+ manwidth = 999
+ elseif vim.env.MANWIDTH then
+ manwidth = vim.env.MANWIDTH
+ else
+ manwidth = api.nvim_win_get_width(0)
+ end
+ -- Force MANPAGER=cat to ensure Vim is not recursively invoked (by man-db).
+ -- http://comments.gmane.org/gmane.editors.vim.devel/29085
+ -- Set MAN_KEEP_FORMATTING so Debian man doesn't discard backspaces.
+ local cmd = { 'env', 'MANPAGER=cat', 'MANWIDTH=' .. manwidth, 'MAN_KEEP_FORMATTING=1', 'man' }
+ if localfile_arg then
+ cmd[#cmd + 1] = '-l'
+ end
+ cmd[#cmd + 1] = path
+ return man_system(cmd, silent)
+end
+
+local function put_page(page)
+ vim.bo.modified = true
+ vim.bo.readonly = false
+ vim.bo.swapfile = false
+
+ api.nvim_buf_set_lines(0, 0, -1, false, vim.split(page, '\n'))
+
+ while fn.getline(1):match('^%s*$') do
+ api.nvim_buf_set_lines(0, 0, 1, false, {})
+ end
+ -- XXX: nroff justifies text by filling it with whitespace. That interacts
+ -- badly with our use of $MANWIDTH=999. Hack around this by using a fixed
+ -- size for those whitespace regions.
+ vim.cmd([[silent! keeppatterns keepjumps %s/\s\{199,}/\=repeat(' ', 10)/g]])
+ vim.cmd('1') -- Move cursor to first line
+ highlight_man_page()
+ set_options(false)
+end
+
+local function format_candidate(path, psect)
+ if matchstr(path, [[\.\%(pdf\|in\)$]]) then -- invalid extensions
+ return ''
+ end
+ local sect, name = extract_sect_and_name_path(path)
+ if sect == psect then
+ return name
+ elseif sect and name and matchstr(sect, psect .. '.\\+$') then -- invalid extensions
+ -- We include the section if the user provided section is a prefix
+ -- of the actual section.
+ return ('%s(%s)'):format(name, sect)
+ end
+ return ''
end
-return { highlight_man_page = highlight_man_page }
+local function get_paths(sect, name, do_fallback)
+ -- callers must try-catch this, as some `man` implementations don't support `s:find_arg`
+ local ok, ret = pcall(function()
+ local mandirs =
+ table.concat(vim.split(man_system({ 'man', find_arg }), '[:\n]', { trimempty = true }), ',')
+ local paths = fn.globpath(mandirs, 'man?/' .. name .. '*.' .. sect .. '*', false, true)
+ pcall(function()
+ -- Prioritize the result from verify_exists as it obeys b:man_default_sects.
+ local first = verify_exists(sect, name)
+ paths = vim.tbl_filter(function(v)
+ return v ~= first
+ end, paths)
+ paths = { first, unpack(paths) }
+ end)
+ return paths
+ end)
+
+ if not ok then
+ if not do_fallback then
+ error(ret)
+ end
+
+ -- Fallback to a single path, with the page we're trying to find.
+ ok, ret = pcall(verify_exists, sect, name)
+
+ return { ok and ret or nil }
+ end
+ return ret or {}
+end
+
+local function complete(sect, psect, name)
+ local pages = get_paths(sect, name, false)
+ -- We remove duplicates in case the same manpage in different languages was found.
+ return fn.uniq(fn.sort(vim.tbl_map(function(v)
+ return format_candidate(v, psect)
+ end, pages) or {}, 'i'))
+end
+
+-- see extract_sect_and_name_ref on why tolower(sect)
+function M.man_complete(arg_lead, cmd_line, _)
+ local args = vim.split(cmd_line, '%s+', { trimempty = true })
+ local cmd_offset = fn.index(args, 'Man')
+ if cmd_offset > 0 then
+ -- Prune all arguments up to :Man itself. Otherwise modifier commands like
+ -- :tab, :vertical, etc. would lead to a wrong length.
+ args = vim.list_slice(args, cmd_offset + 1)
+ end
+
+ if #args > 3 then
+ return {}
+ end
+
+ if #args == 1 then
+ -- returning full completion is laggy. Require some arg_lead to complete
+ -- return complete('', '', '')
+ return {}
+ end
+
+ if arg_lead:match('^[^()]+%([^()]*$') then
+ -- cursor (|) is at ':Man printf(|' or ':Man 1 printf(|'
+ -- The later is is allowed because of ':Man pri<TAB>'.
+ -- It will offer 'priclass.d(1m)' even though section is specified as 1.
+ local tmp = vim.split(arg_lead, '(', { plain = true })
+ local name = tmp[1]
+ local sect = (tmp[2] or ''):lower()
+ return complete(sect, '', name)
+ end
+
+ if not args[2]:match('^[^()]+$') then
+ -- cursor (|) is at ':Man 3() |' or ':Man (3|' or ':Man 3() pri|'
+ -- or ':Man 3() pri |'
+ return {}
+ end
+
+ if #args == 2 then
+ local name, sect
+ if arg_lead == '' then
+ -- cursor (|) is at ':Man 1 |'
+ name = ''
+ sect = args[1]:lower()
+ else
+ -- cursor (|) is at ':Man pri|'
+ if arg_lead:match('/') then
+ -- if the name is a path, complete files
+ -- TODO(nhooyr) why does this complete the last one automatically
+ return fn.glob(arg_lead .. '*', false, true)
+ end
+ name = arg_lead
+ sect = ''
+ end
+ return complete(sect, sect, name)
+ end
+
+ if not arg_lead:match('[^()]+$') then
+ -- cursor (|) is at ':Man 3 printf |' or ':Man 3 (pr)i|'
+ return {}
+ end
+
+ -- cursor (|) is at ':Man 3 pri|'
+ local name = arg_lead
+ local sect = args[2]:lower()
+ return complete(sect, sect, name)
+end
+
+function M.goto_tag(pattern, _, _)
+ local sect, name = extract_sect_and_name_ref(pattern)
+
+ local paths = get_paths(sect, name, true)
+ local structured = {}
+
+ for _, path in ipairs(paths) do
+ sect, name = extract_sect_and_name_path(path)
+ if sect and name then
+ structured[#structured + 1] = {
+ name = name,
+ title = name .. '(' .. sect .. ')',
+ }
+ end
+ end
+
+ if vim.o.cscopetag then
+ -- return only a single entry so we work well with :cstag (#11675)
+ structured = { structured[1] }
+ end
+
+ return vim.tbl_map(function(entry)
+ return {
+ name = entry.name,
+ filename = 'man://' .. entry.title,
+ cmd = '1',
+ }
+ end, structured)
+end
+
+-- Called when Nvim is invoked as $MANPAGER.
+function M.init_pager()
+ if fn.getline(1):match('^%s*$') then
+ api.nvim_buf_set_lines(0, 0, 1, false, {})
+ else
+ vim.cmd('keepjumps 1')
+ end
+ highlight_man_page()
+ -- Guess the ref from the heading (which is usually uppercase, so we cannot
+ -- know the correct casing, cf. `man glDrawArraysInstanced`).
+ local ref = fn.substitute(matchstr(fn.getline(1), [[^[^)]\+)]]) or '', ' ', '_', 'g')
+ local ok, res = pcall(extract_sect_and_name_ref, ref)
+ vim.b.man_sect = ok and res or ''
+
+ if not fn.bufname('%'):match('man://') then -- Avoid duplicate buffers, E95.
+ vim.cmd.file({ 'man://' .. fn.fnameescape(ref):lower(), mods = { silent = true } })
+ end
+
+ set_options(true)
+end
+
+function M.open_page(count, smods, args)
+ if #args > 2 then
+ man_error('too many arguments')
+ end
+
+ local ref
+ if #args == 0 then
+ ref = vim.bo.filetype == 'man' and fn.expand('<cWORD>') or fn.expand('<cword>')
+ if ref == '' then
+ man_error('no identifier under cursor')
+ end
+ elseif #args == 1 then
+ ref = args[1]
+ else
+ -- Combine the name and sect into a manpage reference so that all
+ -- verification/extraction can be kept in a single function.
+ -- If args[2] is a reference as well, that is fine because it is the only
+ -- reference that will match.
+ ref = ('%s(%s)'):format(args[2], args[1])
+ end
+
+ local sect, name = extract_sect_and_name_ref(ref)
+ if count >= 0 then
+ sect = tostring(count)
+ end
+
+ local path = verify_exists(sect, name)
+ sect, name = extract_sect_and_name_path(path)
+
+ local buf = fn.bufnr()
+ local save_tfu = vim.bo[buf].tagfunc
+ vim.bo[buf].tagfunc = "v:lua.require'man'.goto_tag"
+
+ local target = ('%s(%s)'):format(name, sect)
+
+ local ok, ret = pcall(function()
+ if smods.tab == -1 and find_man() then
+ vim.cmd.tag({ target, mods = { silent = true, keepalt = true } })
+ else
+ smods.silent = true
+ smods.keepalt = true
+ vim.cmd.stag({ target, mods = smods })
+ end
+ end)
+
+ vim.bo[buf].tagfunc = save_tfu
+
+ if not ok then
+ error(ret)
+ else
+ set_options(false)
+ end
+
+ vim.b.man_sect = sect
+end
+
+-- Called when a man:// buffer is opened.
+function M.read_page(ref)
+ local sect, name = extract_sect_and_name_ref(ref)
+ local path = verify_exists(sect, name)
+ sect = extract_sect_and_name_path(path)
+ local page = get_page(path)
+ vim.b.man_sect = sect
+ put_page(page)
+end
+
+function M.show_toc()
+ local bufname = fn.bufname('%')
+ local info = fn.getloclist(0, { winid = 1 })
+ if info ~= '' and vim.w[info.winid].qf_toc == bufname then
+ vim.cmd.lopen()
+ return
+ end
+
+ local toc = {}
+ local lnum = 2
+ local last_line = fn.line('$') - 1
+ local section_title_re = vim.regex([[^\%( \{3\}\)\=\S.*$]])
+ local flag_title_re = vim.regex([[^\s\+\%(+\|-\)\S\+]])
+ while lnum and lnum < last_line do
+ local text = fn.getline(lnum)
+ if section_title_re:match_str(text) then
+ -- if text is a section title
+ toc[#toc + 1] = {
+ bufnr = fn.bufnr('%'),
+ lnum = lnum,
+ text = text,
+ }
+ elseif flag_title_re:match_str(text) then
+ -- if text is a flag title. we strip whitespaces and prepend two
+ -- spaces to have a consistent format in the loclist.
+ toc[#toc + 1] = {
+ bufnr = fn.bufnr('%'),
+ lnum = lnum,
+ text = ' ' .. fn.substitute(text, [[^\s*\(.\{-}\)\s*$]], [[\1]], ''),
+ }
+ end
+ lnum = fn.nextnonblank(lnum + 1)
+ end
+
+ fn.setloclist(0, toc, ' ')
+ fn.setloclist(0, {}, 'a', { title = 'Man TOC' })
+ vim.cmd.lopen()
+ vim.w.qf_toc = bufname
+end
+
+local function init()
+ local path = get_path('', 'man', true)
+ local page
+ if path ~= nil then
+ -- Check for -l support.
+ page = get_page(path, true)
+ end
+
+ if page == '' or page == nil then
+ localfile_arg = false
+ end
+end
+
+init()
+
+return M
diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua
index f1652718ee..0f45c916dc 100644
--- a/runtime/lua/vim/_meta.lua
+++ b/runtime/lua/vim/_meta.lua
@@ -198,7 +198,10 @@ end
-- Can be done in a separate PR.
local key_value_options = {
fillchars = true,
+ fcs = true,
listchars = true,
+ lcs = true,
+ winhighlight = true,
winhl = true,
}
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index 3f71d4f70d..4f7d8cccd5 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('DiagnosticBufWipeout', {})
+ diagnostic_cache = setmetatable({}, {
+ __index = function(t, bufnr)
+ assert(bufnr > 0, 'Invalid buffer number')
+ vim.api.nvim_create_autocmd('BufWipeout', {
+ 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..39985c948e 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -177,6 +177,7 @@ local extension = {
bbappend = 'bitbake',
bbclass = 'bitbake',
bl = 'blank',
+ blp = 'blueprint',
bsd = 'bsdl',
bsdl = 'bsdl',
bst = 'bst',
@@ -422,9 +423,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',
@@ -538,6 +541,7 @@ local extension = {
mjs = 'javascript',
javascript = 'javascript',
js = 'javascript',
+ jsm = 'javascript',
cjs = 'javascript',
jsx = 'javascriptreact',
clp = 'jess',
@@ -554,6 +558,8 @@ local extension = {
['json-patch'] = 'json',
json5 = 'json5',
jsonc = 'jsonc',
+ jsonnet = 'jsonnet',
+ libjsonnet = 'jsonnet',
jsp = 'jsp',
jl = 'julia',
kv = 'kivy',
@@ -741,6 +747,7 @@ local extension = {
php = 'php',
phpt = 'php',
phtml = 'php',
+ theme = 'php',
pike = 'pike',
pmod = 'pike',
rcp = 'pilrc',
@@ -900,7 +907,9 @@ local extension = {
sig = function(path, bufnr)
return require('vim.filetype.detect').sig(bufnr)
end,
- sil = 'sil',
+ sil = function(path, bufnr)
+ return require('vim.filetype.detect').sil(bufnr)
+ end,
sim = 'simula',
['s85'] = 'sinda',
sin = 'sinda',
@@ -950,6 +959,7 @@ local extension = {
srec = 'srec',
mot = 'srec',
['s19'] = 'srec',
+ srt = 'srt',
st = 'st',
imata = 'stata',
['do'] = 'stata',
@@ -1011,6 +1021,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',
@@ -1371,6 +1386,8 @@ local filename = {
['EDIT_DESCRIPTION'] = 'gitcommit',
['.gitconfig'] = 'gitconfig',
['.gitmodules'] = 'gitconfig',
+ ['.gitattributes'] = 'gitattributes',
+ ['.gitignore'] = 'gitignore',
['gitolite.conf'] = 'gitolite',
['git-rebase-todo'] = 'gitrebase',
gkrellmrc = 'gkrellmrc',
@@ -1813,6 +1830,21 @@ local pattern = {
return 'gitconfig'
end
end,
+ ['.*%.git/info/attributes'] = 'gitattributes',
+ ['.*/etc/gitattributes'] = 'gitattributes',
+ ['.*/%.config/git/attributes'] = 'gitattributes',
+ ['.*/git/attributes'] = function(path, bufnr)
+ if vim.env.XDG_CONFIG_HOME and path:find(vim.env.XDG_CONFIG_HOME .. '/git/attributes') then
+ return 'gitattributes'
+ end
+ end,
+ ['.*%.git/info/exclude'] = 'gitignore',
+ ['.*/%.config/git/ignore'] = 'gitignore',
+ ['.*/git/ignore'] = function(path, bufnr)
+ if vim.env.XDG_CONFIG_HOME and path:find(vim.env.XDG_CONFIG_HOME .. '/git/ignore') then
+ return 'gitignore'
+ end
+ end,
['%.gitsendemail%.msg%.......'] = 'gitsendemail',
['gkrellmrc_.'] = 'gkrellmrc',
['.*/usr/.*/gnupg/options%.skel'] = 'gpg',
diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua
index 2be9dcff88..7fc7f1b7ca 100644
--- a/runtime/lua/vim/filetype/detect.lua
+++ b/runtime/lua/vim/filetype/detect.lua
@@ -1194,6 +1194,19 @@ function M.shell(path, contents, name)
return name
end
+-- Swift Intermediate Language or SILE
+function M.sil(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 100)) do
+ if line:find('^%s*[\\%%]') then
+ return 'sile'
+ elseif line:find('^%s*%S') then
+ return 'sil'
+ end
+ end
+ -- No clue, default to "sil"
+ return 'sil'
+end
+
-- SMIL or SNMP MIB file
function M.smi(bufnr)
local line = getlines(bufnr, 1)
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..22933d8143 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`.
@@ -1134,41 +1147,47 @@ function lsp.start_client(config)
local namespace = vim.lsp.diagnostic.get_namespace(client_id)
vim.diagnostic.reset(namespace, bufnr)
- end)
- client_ids[client_id] = nil
- end
- if vim.tbl_isempty(client_ids) then
- vim.schedule(function()
- unset_defaults(bufnr)
+ client_ids[client_id] = nil
+ if vim.tbl_isempty(client_ids) then
+ unset_defaults(bufnr)
+ end
end)
end
end
- local client = active_clients[client_id] and active_clients[client_id]
- or uninitialized_clients[client_id]
- active_clients[client_id] = nil
- uninitialized_clients[client_id] = nil
- -- Client can be absent if executable starts, but initialize fails
- -- init/attach won't have happened
- if client then
- changetracking.reset(client)
- end
- if code ~= 0 or (signal ~= 0 and signal ~= 15) then
- local msg =
- string.format('Client %s quit with exit code %s and signal %s', client_id, code, signal)
- vim.schedule(function()
+ -- Schedule the deletion of the client object so that it exists in the execution of LspDetach
+ -- autocommands
+ vim.schedule(function()
+ local client = active_clients[client_id] and active_clients[client_id]
+ or uninitialized_clients[client_id]
+ active_clients[client_id] = nil
+ uninitialized_clients[client_id] = nil
+
+ -- Client can be absent if executable starts, but initialize fails
+ -- init/attach won't have happened
+ if client then
+ changetracking.reset(client)
+ end
+ if code ~= 0 or (signal ~= 0 and signal ~= 15) then
+ local msg =
+ string.format('Client %s quit with exit code %s and signal %s', client_id, code, signal)
vim.notify(msg, vim.log.levels.WARN)
- end)
- end
+ end
+ end)
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 +1483,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 +1498,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 +1510,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
@@ -1627,6 +1645,7 @@ function lsp.buf_attach_client(bufnr, client_id)
if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then
client.notify('textDocument/didClose', params)
end
+ client.attached_buffers[bufnr] = nil
end)
util.buf_versions[bufnr] = nil
all_buffer_active_clients[bufnr] = nil
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 6a070928d9..2ce565e1d9 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -150,6 +150,33 @@ local function select_client(method, on_choice)
end
end
+---@private
+---@return table {start={row, col}, end={row, col}} using (1, 0) indexing
+local function range_from_selection()
+ -- TODO: Use `vim.region()` instead https://github.com/neovim/neovim/pull/13896
+
+ -- [bufnum, lnum, col, off]; both row and column 1-indexed
+ local start = vim.fn.getpos('v')
+ local end_ = vim.fn.getpos('.')
+ local start_row = start[2]
+ local start_col = start[3]
+ local end_row = end_[2]
+ local end_col = end_[3]
+
+ -- A user can start visual selection at the end and move backwards
+ -- Normalize the range to start < end
+ if start_row == end_row and end_col < start_col then
+ end_col, start_col = start_col, end_col
+ elseif end_row < start_row then
+ start_row, end_row = end_row, start_row
+ start_col, end_col = end_col, start_col
+ end
+ return {
+ ['start'] = { start_row, start_col - 1 },
+ ['end'] = { end_row, end_col - 1 },
+ }
+end
+
--- Formats a buffer using the attached (and optionally filtered) language
--- server clients.
---
@@ -184,7 +211,12 @@ end
--- Restrict formatting to the client with ID (client.id) matching this field.
--- - name (string|nil):
--- Restrict formatting to the client with name (client.name) matching this field.
-
+---
+--- - range (table|nil) Range to format.
+--- Table must contain `start` and `end` keys with {row, col} tuples using
+--- (1,0) indexing.
+--- Defaults to current selection in visual mode
+--- Defaults to `nil` in other modes, formatting the full buffer
function M.format(options)
options = options or {}
local bufnr = options.bufnr or api.nvim_get_current_buf()
@@ -206,16 +238,32 @@ function M.format(options)
vim.notify('[LSP] Format request failed, no matching language servers.')
end
+ local mode = api.nvim_get_mode().mode
+ local range = options.range
+ if not range and mode == 'v' or mode == 'V' then
+ range = range_from_selection()
+ end
+
+ ---@private
+ local function set_range(client, params)
+ if range then
+ local range_params =
+ util.make_given_range_params(range.start, range['end'], bufnr, client.offset_encoding)
+ params.range = range_params.range
+ end
+ return params
+ end
+
+ local method = range and 'textDocument/rangeFormatting' or 'textDocument/formatting'
if options.async then
local do_format
do_format = function(idx, client)
if not client then
return
end
- local params = util.make_formatting_params(options.formatting_options)
- client.request('textDocument/formatting', params, function(...)
- local handler = client.handlers['textDocument/formatting']
- or vim.lsp.handlers['textDocument/formatting']
+ local params = set_range(client, util.make_formatting_params(options.formatting_options))
+ client.request(method, params, function(...)
+ local handler = client.handlers[method] or vim.lsp.handlers[method]
handler(...)
do_format(next(clients, idx))
end, bufnr)
@@ -224,8 +272,8 @@ function M.format(options)
else
local timeout_ms = options.timeout_ms or 1000
for _, client in pairs(clients) do
- local params = util.make_formatting_params(options.formatting_options)
- local result, err = client.request_sync('textDocument/formatting', params, timeout_ms, bufnr)
+ local params = set_range(client, util.make_formatting_params(options.formatting_options))
+ local result, err = client.request_sync(method, params, timeout_ms, bufnr)
if result and result.result then
util.apply_text_edits(result.result, bufnr, client.offset_encoding)
elseif err then
@@ -356,6 +404,7 @@ end
---@param end_pos ({number, number}, optional) mark-indexed position.
---Defaults to the end of the last visual selection.
function M.range_formatting(options, start_pos, end_pos)
+ vim.deprecate('vim.lsp.buf.range_formatting', 'vim.lsp.formatexpr or vim.lsp.format', '0.9.0')
local params = util.make_given_range_params(start_pos, end_pos)
params.options = util.make_formatting_params(options).options
select_client('textDocument/rangeFormatting', function(client)
@@ -885,23 +934,8 @@ function M.code_action(options)
local end_ = assert(options.range['end'], 'range must have a `end` property')
params = util.make_given_range_params(start, end_)
elseif mode == 'v' or mode == 'V' then
- -- [bufnum, lnum, col, off]; both row and column 1-indexed
- local start = vim.fn.getpos('v')
- local end_ = vim.fn.getpos('.')
- local start_row = start[2]
- local start_col = start[3]
- local end_row = end_[2]
- local end_col = end_[3]
-
- -- A user can start visual selection at the end and move backwards
- -- Normalize the range to start < end
- if start_row == end_row and end_col < start_col then
- end_col, start_col = start_col, end_col
- elseif end_row < start_row then
- start_row, end_row = end_row, start_row
- start_col, end_col = end_col, start_col
- end
- params = util.make_given_range_params({ start_row, start_col - 1 }, { end_row, end_col - 1 })
+ local range = range_from_selection()
+ params = util.make_given_range_params(range.start, range['end'])
else
params = util.make_range_params()
end
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 0926912066..7d047f8958 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -241,8 +241,402 @@ 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.
+--- interact with it. Communication with the spawned process happens via stdio. For
+--- communication via TCP, spawn a process manually and use |vim.lsp.rpc.connect|
---
---@param cmd (string) Command to start the LSP server.
---@param cmd_args (table) List of additional string arguments to pass to {cmd}.
@@ -261,11 +655,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 +669,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 +735,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/shared.lua b/runtime/lua/vim/shared.lua
index e1b4ed4ea9..59cb669609 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -715,5 +715,30 @@ function vim.is_callable(f)
return type(m.__call) == 'function'
end
+--- Creates a table whose members are automatically created when accessed, if they don't already
+--- exist.
+---
+--- They mimic defaultdict in python.
+---
+--- If @p create is @c nil, this will create a defaulttable whose constructor function is
+--- this function, effectively allowing to create nested tables on the fly:
+---
+--- <pre>
+--- local a = vim.defaulttable()
+--- a.b.c = 1
+--- </pre>
+---
+---@param create function|nil The function called to create a missing value.
+---@return table Empty table with metamethod
+function vim.defaulttable(create)
+ create = create or vim.defaulttable
+ return setmetatable({}, {
+ __index = function(tbl, key)
+ rawset(tbl, key, create())
+ return rawget(tbl, key)
+ end,
+ })
+end
+
return vim
-- vim:sw=2 ts=2 et
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 70f2c425ed..d93c485dfe 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -3,10 +3,7 @@ local query = require('vim.treesitter.query')
local language = require('vim.treesitter.language')
local LanguageTree = require('vim.treesitter.languagetree')
--- TODO(bfredl): currently we retain parsers for the lifetime of the buffer.
--- Consider use weak references to release parser if all plugins are done with
--- it.
-local parsers = {}
+local parsers = setmetatable({}, { __mode = 'v' })
local M = vim.tbl_extend('error', query, language)
@@ -32,9 +29,11 @@ setmetatable(M, {
---
--- It is not recommended to use this, use vim.treesitter.get_parser() instead.
---
----@param bufnr The buffer the parser will be tied to
----@param lang The language of the parser
----@param opts Options to pass to the created language tree
+---@param bufnr string Buffer the parser will be tied to (0 for current buffer)
+---@param lang string Language of the parser
+---@param opts table|nil Options to pass to the created language tree
+---
+---@returns table Created parser object
function M._create_parser(bufnr, lang, opts)
language.require_language(lang)
if bufnr == 0 then
@@ -79,11 +78,11 @@ end
--- If needed this will create the parser.
--- Unconditionally attach the provided callback
---
----@param bufnr The buffer the parser should be tied to
----@param lang The filetype of this parser
----@param opts Options object to pass to the created language tree
+---@param bufnr number|nil Buffer the parser should be tied to (default: current buffer)
+---@param lang string |nil Filetype of this parser (default: buffer filetype)
+---@param opts table|nil Options to pass to the created language tree
---
----@returns The parser
+---@returns table Parser object
function M.get_parser(bufnr, lang, opts)
opts = opts or {}
@@ -118,4 +117,234 @@ 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 Possible ancestor
+---@param source table 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 table 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 table Node defining the range
+---@param line number Line (0-based)
+---@param col number Column (0-based)
+---
+---@returns (boolean) True if the position is in node range
+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
+---@param range table
+---
+---@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 Buffer number (0 for current buffer)
+---@param row number Position row
+---@param col number Position column
+---
+---@param bufnr number Buffer number (0 for current buffer)
+---@param row number Position row
+---@param col number Position column
+---
+---@returns (table) 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
+
+---Gets a list of captures under the cursor
+---
+---@param winnr number|nil Window handle or 0 for current window (default)
+---
+---@returns (table) Named node under the cursor
+function M.get_captures_at_cursor(winnr)
+ winnr = winnr or 0
+ local bufnr = a.nvim_win_get_buf(winnr)
+ local cursor = a.nvim_win_get_cursor(winnr)
+
+ local data = M.get_captures_at_position(bufnr, cursor[1] - 1, cursor[2])
+
+ local captures = {}
+
+ for _, capture in ipairs(data) do
+ table.insert(captures, capture.capture)
+ end
+
+ return captures
+end
+
+--- Gets the smallest named node at position
+---
+---@param bufnr number Buffer number (0 for current buffer)
+---@param row number Position row
+---@param col number Position column
+---@param opts table Optional keyword arguments:
+--- - ignore_injections boolean Ignore injected languages (default true)
+---
+---@returns (table) Named node under the cursor
+function M.get_node_at_position(bufnr, row, col, opts)
+ if bufnr == 0 then
+ bufnr = a.nvim_get_current_buf()
+ end
+ local ts_range = { row, col, row, col }
+
+ local root_lang_tree = M.get_parser(bufnr)
+ if not root_lang_tree then
+ return
+ end
+
+ return root_lang_tree:named_node_for_range(ts_range, opts)
+end
+
+--- Gets the smallest named node under the cursor
+---
+---@param winnr number|nil Window handle or 0 for current window (default)
+---
+---@returns (string) Named node under the cursor
+function M.get_node_at_cursor(winnr)
+ winnr = winnr or 0
+ local bufnr = a.nvim_win_get_buf(winnr)
+ local cursor = a.nvim_win_get_cursor(winnr)
+
+ return M.get_node_at_position(bufnr, cursor[1] - 1, cursor[2], { ignore_injections = false })
+ :type()
+end
+
+--- Start treesitter highlighting for a buffer
+---
+--- Can be used in an ftplugin or FileType autocommand
+---
+--- Note: By default, disables regex syntax highlighting, which may be required for some plugins.
+--- In this case, add ``vim.bo.syntax = 'on'`` after the call to `start`.
+---
+--- Example:
+---
+--- <pre>
+--- vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex',
+--- callback = function(args)
+--- vim.treesitter.start(args.buf, 'latex')
+--- vim.bo[args.buf].syntax = 'on' -- only if additional legacy syntax is needed
+--- end
+--- })
+--- </pre>
+---
+---@param bufnr number|nil Buffer to be highlighted (default: current buffer)
+---@param lang string|nil Language of the parser (default: buffer filetype)
+function M.start(bufnr, lang)
+ bufnr = bufnr or a.nvim_get_current_buf()
+
+ local parser = M.get_parser(bufnr, lang)
+
+ M.highlighter.new(parser)
+
+ vim.b[bufnr].ts_highlight = true
+end
+
+---Stop treesitter highlighting for a buffer
+---
+---@param bufnr number|nil Buffer to stop highlighting (default: current buffer)
+function M.stop(bufnr)
+ bufnr = bufnr or a.nvim_get_current_buf()
+
+ if M.highlighter.active[bufnr] then
+ M.highlighter.active[bufnr]:destroy()
+ end
+
+ vim.bo[bufnr].syntax = 'on'
+end
+
return M
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index e27a5fa9c3..1e625eddb8 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
@@ -187,7 +86,7 @@ function TSHighlighter.new(tree, opts)
end
end
- a.nvim_buf_set_option(self.bufnr, 'syntax', '')
+ vim.bo[self.bufnr].syntax = ''
TSHighlighter.active[self.bufnr] = self
@@ -196,9 +95,13 @@ function TSHighlighter.new(tree, opts)
-- syntax FileType autocmds. Later on we should integrate with the
-- `:syntax` and `set syntax=...` machinery properly.
if vim.g.syntax_on ~= 1 then
- vim.api.nvim_command('runtime! syntax/synload.vim')
+ vim.cmd.runtime({ 'syntax/synload.vim', bang = true })
end
+ a.nvim_buf_call(self.bufnr, function()
+ vim.opt_local.spelloptions:append('noplainbuffer')
+ end)
+
self.tree:parse()
return self
@@ -257,7 +160,7 @@ function TSHighlighter:get_query(lang)
end
---@private
-local function on_line_impl(self, buf, line)
+local function on_line_impl(self, buf, line, spell)
self.tree:for_each_tree(function(tstree, tree)
if not tstree then
return
@@ -294,7 +197,9 @@ local function on_line_impl(self, buf, line)
local start_row, start_col, end_row, end_col = node:range()
local hl = highlighter_query.hl_cache[capture]
- if hl and end_row >= line then
+ local is_spell = highlighter_query:query().captures[capture] == 'spell'
+
+ if hl and end_row >= line and (not spell or is_spell) then
a.nvim_buf_set_extmark(buf, ns, start_row, start_col, {
end_line = end_row,
end_col = end_col,
@@ -302,6 +207,7 @@ local function on_line_impl(self, buf, line)
ephemeral = true,
priority = tonumber(metadata.priority) or 100, -- Low but leaves room below
conceal = metadata.conceal,
+ spell = is_spell,
})
end
if start_row > line then
@@ -318,7 +224,21 @@ function TSHighlighter._on_line(_, _win, buf, line, _)
return
end
- on_line_impl(self, buf, line)
+ on_line_impl(self, buf, line, false)
+end
+
+---@private
+function TSHighlighter._on_spell_nav(_, _, buf, srow, _, erow, _)
+ local self = TSHighlighter.active[buf]
+ if not self then
+ return
+ end
+
+ self:reset_highlight_state()
+
+ for row = srow, erow do
+ on_line_impl(self, buf, row, true)
+ end
end
---@private
@@ -345,6 +265,7 @@ a.nvim_set_decoration_provider(ns, {
on_buf = TSHighlighter._on_buf,
on_win = TSHighlighter._on_win,
on_line = TSHighlighter._on_line,
+ _on_spell_nav = TSHighlighter._on_spell_nav,
})
return TSHighlighter
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..90ed2a357c 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -34,6 +34,18 @@ local function safe_read(filename, read_quantifier)
return content
end
+---@private
+--- Adds @p ilang to @p base_langs, only if @p ilang is different than @lang
+---
+---@return boolean true it lang == ilang
+local function add_included_lang(base_langs, lang, ilang)
+ if lang == ilang then
+ return true
+ end
+ table.insert(base_langs, ilang)
+ return false
+end
+
--- Gets the list of files used to make up a query
---
---@param lang The language
@@ -47,6 +59,9 @@ function M.get_query_files(lang, query_name, is_included)
return {}
end
+ local base_query = nil
+ local extensions = {}
+
local base_langs = {}
-- Now get the base languages by looking at the first line of every file
@@ -55,35 +70,61 @@ function M.get_query_files(lang, query_name, is_included)
--
-- {language} ::= {lang} | ({lang})
local MODELINE_FORMAT = '^;+%s*inherits%s*:?%s*([a-z_,()]+)%s*$'
+ local EXTENDS_FORMAT = '^;+%s*extends%s*$'
- for _, file in ipairs(lang_files) do
- local modeline = safe_read(file, '*l')
+ for _, filename in ipairs(lang_files) do
+ local file, err = io.open(filename, 'r')
+ if not file then
+ error(err)
+ end
- if modeline then
- local langlist = modeline:match(MODELINE_FORMAT)
+ local extension = false
+ for modeline in
+ function()
+ return file:read('*l')
+ end
+ do
+ if not vim.startswith(modeline, ';') then
+ break
+ end
+
+ local langlist = modeline:match(MODELINE_FORMAT)
if langlist then
for _, incllang in ipairs(vim.split(langlist, ',', true)) do
local is_optional = incllang:match('%(.*%)')
if is_optional then
if not is_included then
- table.insert(base_langs, incllang:sub(2, #incllang - 1))
+ if add_included_lang(base_langs, lang, incllang:sub(2, #incllang - 1)) then
+ extension = true
+ end
end
else
- table.insert(base_langs, incllang)
+ if add_included_lang(base_langs, lang, incllang) then
+ extension = true
+ end
end
end
+ elseif modeline:match(EXTENDS_FORMAT) then
+ extension = true
end
end
+
+ if extension then
+ table.insert(extensions, filename)
+ elseif base_query == nil then
+ base_query = filename
+ end
+ io.close(file)
end
- local query_files = {}
+ local query_files = { base_query }
for _, base_lang in ipairs(base_langs) do
local base_files = M.get_query_files(base_lang, query_name, true)
vim.list_extend(query_files, base_files)
end
- vim.list_extend(query_files, lang_files)
+ vim.list_extend(query_files, extensions)
return query_files
end
@@ -140,12 +181,9 @@ function M.get_query(lang, query_name)
end
end
-local query_cache = setmetatable({}, {
- __index = function(tbl, key)
- rawset(tbl, key, {})
- return rawget(tbl, key)
- end,
-})
+local query_cache = vim.defaulttable(function()
+ return setmetatable({}, { __mode = 'v' })
+end)
--- Parse {query} as a string. (If the query is in a file, the caller
--- should read the contents into a string before calling).
@@ -181,9 +219,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 +253,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/lua/vim/usermark.lua b/runtime/lua/vim/usermark.lua
new file mode 100644
index 0000000000..0d1ec0ae0f
--- /dev/null
+++ b/runtime/lua/vim/usermark.lua
@@ -0,0 +1,68 @@
+-- Defualt implementation of the usermarkfunc. This default implementation is
+-- extensible and allows other plugins to register handlers for different
+-- registers.
+--
+-- The default handler behaves just as a normal register would.
+
+local vim = assert(vim)
+local usermark = {}
+
+-- Returns a "default handler" which behaves like normal global marks. When a
+-- call to set() is made, it stores the current line and col of the cursor and
+-- the filename of the current file.
+function usermark._default_handler()
+ local d = {}
+
+ -- Called when a mark is recalled using the "'" command. Just returns what was
+ -- stored before or nothing if it was never set before.
+ function d.get(self, mark)
+ return self.content or {}
+ end
+
+ -- Called when a mark is set using the "m" command. Stores the current cursor
+ -- position to be recalled at a later time.
+ function d.set(self, mark)
+ local r,c = unpack(vim.api.nvim_win_get_cursor(0))
+ local file = vim.fn.expand("%:p")
+
+ self.content = {
+ line = r;
+ col = c;
+ }
+
+ if file ~= '' then
+ self.content.file = file
+ end
+ end
+
+ return d
+end
+
+-- The store for register default handler
+usermark._marktable = {}
+
+-- Function for the 'usermarkfunc'. Will defer to the handler associated with
+-- the provided mark.
+--
+-- If not handler is registered to a given mark, the default handler is used,
+-- which is a re-implementation of standard mark behavior.
+function usermark.fn(action, mark)
+ if not usermark._marktable[mark] then
+ usermark._marktable[mark] = usermark._default_handler()
+ end
+
+ if action == "get" then
+ return usermark._marktable[mark]:get(mark)
+ else
+ usermark._marktable[mark]:set(mark)
+ return nil
+ end
+end
+
+-- Registers a handler with a mark. Gets and sets will then defer to this
+-- handler when determining the mark's behavior.
+function usermark.register_handler(mark, handler)
+ usermark._marktable[mark] = handler
+end
+
+return usermark
diff --git a/runtime/lua/vim/userreg.lua b/runtime/lua/vim/userreg.lua
new file mode 100644
index 0000000000..5abcff0407
--- /dev/null
+++ b/runtime/lua/vim/userreg.lua
@@ -0,0 +1,51 @@
+-- Defualt implementation of the userregfunc. This default implementation is
+-- extensible and allows other plugins to register handlers for different
+-- registers.
+--
+-- The default handler behaves just as a normal register would.
+
+local userreg = {}
+
+-- Returns a "default handler" which behaves exactly like the builtin registers
+-- in Vim. Simply stores whatever was yanked and returns the last thing that was
+-- yanked.
+function userreg._default_handler()
+ local d = {}
+
+ function d.do_yank(self, content)
+ self.content = content
+ end
+
+ function d.do_put(self)
+ return self.content or {}
+ end
+
+ return d
+end
+
+-- The store for registers default handler
+userreg._regtable = {}
+
+-- Function for the userreg. This function will defer to the handler registered
+-- to the given register. If no handler is registered to the given register, the
+-- default handler is used.
+function userreg.fn(action, register, content)
+ if not userreg._regtable[register] then
+ userreg._regtable[register] = userreg._default_handler()
+ end
+
+ if action == "yank" then
+ userreg._regtable[register]:do_yank(content)
+ return nil
+ else
+ return userreg._regtable[register]:do_put()
+ end
+end
+
+-- Registers a handler with a register. Future yanks and puts will defer to the
+-- handler when determining the content to put/yank.
+function userreg.register_handler(register, handler)
+ userreg._regtable[register] = handler
+end
+
+return userreg
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index 802ebd42b5..bfece6aa72 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -964,14 +964,7 @@ func s:DeleteCommands()
nunmap K
else
" call mapset(s:k_map_saved)
- let mode = s:k_map_saved.mode !=# ' ' ? s:k_map_saved.mode : ''
- call nvim_set_keymap(mode, 'K', s:k_map_saved.rhs, {
- \ 'expr': s:k_map_saved.expr ? v:true : v:false,
- \ 'noremap': s:k_map_saved.noremap ? v:true : v:false,
- \ 'nowait': s:k_map_saved.nowait ? v:true : v:false,
- \ 'script': s:k_map_saved.script ? v:true : v:false,
- \ 'silent': s:k_map_saved.silent ? v:true : v:false,
- \ })
+ call mapset('n', 0, s:k_map_saved)
endif
unlet s:k_map_saved
endif
diff --git a/runtime/plugin/man.lua b/runtime/plugin/man.lua
new file mode 100644
index 0000000000..4b1528b0cb
--- /dev/null
+++ b/runtime/plugin/man.lua
@@ -0,0 +1,34 @@
+if vim.g.loaded_man ~= nil then
+ return
+end
+vim.g.loaded_man = true
+
+vim.api.nvim_create_user_command('Man', function(params)
+ local man = require('man')
+ if params.bang then
+ man.init_pager()
+ else
+ local ok, err = pcall(man.open_page, params.count, params.smods, params.fargs)
+ if not ok then
+ vim.notify(man.errormsg or err, vim.log.levels.ERROR)
+ end
+ end
+end, {
+ bang = true,
+ bar = true,
+ addr = 'other',
+ nargs = '*',
+ complete = function(...)
+ return require('man').man_complete(...)
+ end,
+})
+
+local augroup = vim.api.nvim_create_augroup('man', {})
+
+vim.api.nvim_create_autocmd('BufReadCmd', {
+ group = augroup,
+ pattern = 'man://*',
+ callback = function(params)
+ require('man').read_page(vim.fn.matchstr(params.match, 'man://\\zs.*'))
+ end,
+})
diff --git a/runtime/plugin/man.vim b/runtime/plugin/man.vim
deleted file mode 100644
index b10677593f..0000000000
--- a/runtime/plugin/man.vim
+++ /dev/null
@@ -1,15 +0,0 @@
-" Maintainer: Anmol Sethi <hi@nhooyr.io>
-
-if exists('g:loaded_man')
- finish
-endif
-let g:loaded_man = 1
-
-command! -bang -bar -addr=other -complete=customlist,man#complete -nargs=* Man
- \ if <bang>0 | call man#init_pager() |
- \ else | call man#open_page(<count>, <q-mods>, <f-args>) | endif
-
-augroup man
- autocmd!
- autocmd BufReadCmd man://* call man#read_page(matchstr(expand('<amatch>'), 'man://\zs.*'))
-augroup 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/plugin/usermark.vim b/runtime/plugin/usermark.vim
new file mode 100644
index 0000000000..917e7510f1
--- /dev/null
+++ b/runtime/plugin/usermark.vim
@@ -0,0 +1 @@
+set usermarkfunc=usermark#func
diff --git a/runtime/plugin/userreg.vim b/runtime/plugin/userreg.vim
new file mode 100644
index 0000000000..099e7c65cb
--- /dev/null
+++ b/runtime/plugin/userreg.vim
@@ -0,0 +1 @@
+set userregfunc=userreg#func
diff --git a/runtime/queries/c/highlights.scm b/runtime/queries/c/highlights.scm
index 260750a85b..33e6df74ab 100644
--- a/runtime/queries/c/highlights.scm
+++ b/runtime/queries/c/highlights.scm
@@ -101,6 +101,7 @@
[ "(" ")" "[" "]" "{" "}"] @punctuation.bracket
(string_literal) @string
+(string_literal) @spell
(system_lib_string) @string
(null) @constant.builtin
@@ -148,6 +149,7 @@
(comment) @comment
+(comment) @spell
;; Parameters
(parameter_declaration
diff --git a/runtime/queries/c/injections.scm b/runtime/queries/c/injections.scm
new file mode 100644
index 0000000000..7e9e73449d
--- /dev/null
+++ b/runtime/queries/c/injections.scm
@@ -0,0 +1,3 @@
+(preproc_arg) @c
+
+; (comment) @comment
diff --git a/runtime/queries/lua/highlights.scm b/runtime/queries/lua/highlights.scm
new file mode 100644
index 0000000000..054d787932
--- /dev/null
+++ b/runtime/queries/lua/highlights.scm
@@ -0,0 +1,194 @@
+;; Keywords
+
+"return" @keyword.return
+
+[
+ "goto"
+ "in"
+ "local"
+] @keyword
+
+(label_statement) @label
+
+(break_statement) @keyword
+
+(do_statement
+[
+ "do"
+ "end"
+] @keyword)
+
+(while_statement
+[
+ "while"
+ "do"
+ "end"
+] @repeat)
+
+(repeat_statement
+[
+ "repeat"
+ "until"
+] @repeat)
+
+(if_statement
+[
+ "if"
+ "elseif"
+ "else"
+ "then"
+ "end"
+] @conditional)
+
+(elseif_statement
+[
+ "elseif"
+ "then"
+ "end"
+] @conditional)
+
+(else_statement
+[
+ "else"
+ "end"
+] @conditional)
+
+(for_statement
+[
+ "for"
+ "do"
+ "end"
+] @repeat)
+
+(function_declaration
+[
+ "function"
+ "end"
+] @keyword.function)
+
+(function_definition
+[
+ "function"
+ "end"
+] @keyword.function)
+
+;; Operators
+
+[
+ "and"
+ "not"
+ "or"
+] @keyword.operator
+
+[
+ "+"
+ "-"
+ "*"
+ "/"
+ "%"
+ "^"
+ "#"
+ "=="
+ "~="
+ "<="
+ ">="
+ "<"
+ ">"
+ "="
+ "&"
+ "~"
+ "|"
+ "<<"
+ ">>"
+ "//"
+ ".."
+] @operator
+
+;; Punctuations
+
+[
+ ";"
+ ":"
+ ","
+ "."
+] @punctuation.delimiter
+
+;; Brackets
+
+[
+ "("
+ ")"
+ "["
+ "]"
+ "{"
+ "}"
+] @punctuation.bracket
+
+;; Variables
+
+(identifier) @variable
+
+((identifier) @variable.builtin
+ (#eq? @variable.builtin "self"))
+
+;; Constants
+
+((identifier) @constant
+ (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
+
+(vararg_expression) @constant
+
+(nil) @constant.builtin
+
+[
+ (false)
+ (true)
+] @boolean
+
+;; Tables
+
+(field name: (identifier) @field)
+
+(dot_index_expression field: (identifier) @field)
+
+(table_constructor
+[
+ "{"
+ "}"
+] @constructor)
+
+;; Functions
+
+(parameters (identifier) @parameter)
+
+(function_call name: (identifier) @function.call)
+(function_declaration name: (identifier) @function)
+
+(function_call name: (dot_index_expression field: (identifier) @function.call))
+(function_declaration name: (dot_index_expression field: (identifier) @function))
+
+(method_index_expression method: (identifier) @method)
+
+(function_call
+ (identifier) @function.builtin
+ (#any-of? @function.builtin
+ ;; built-in functions in Lua 5.1
+ "assert" "collectgarbage" "dofile" "error" "getfenv" "getmetatable" "ipairs"
+ "load" "loadfile" "loadstring" "module" "next" "pairs" "pcall" "print"
+ "rawequal" "rawget" "rawset" "require" "select" "setfenv" "setmetatable"
+ "tonumber" "tostring" "type" "unpack" "xpcall"))
+
+;; Others
+
+(comment) @comment
+(comment) @spell
+
+(hash_bang_line) @comment
+
+(number) @number
+
+(string) @string
+(string) @spell
+
+;; Error
+(ERROR) @error
diff --git a/runtime/queries/lua/injections.scm b/runtime/queries/lua/injections.scm
new file mode 100644
index 0000000000..0e67329139
--- /dev/null
+++ b/runtime/queries/lua/injections.scm
@@ -0,0 +1,22 @@
+((function_call
+ name: [
+ (identifier) @_cdef_identifier
+ (_ _ (identifier) @_cdef_identifier)
+ ]
+ arguments: (arguments (string content: _ @c)))
+ (#eq? @_cdef_identifier "cdef"))
+
+((function_call
+ name: (_) @_vimcmd_identifier
+ arguments: (arguments (string content: _ @vim)))
+ (#any-of? @_vimcmd_identifier "vim.cmd" "vim.api.nvim_command" "vim.api.nvim_exec" "vim.api.nvim_cmd"))
+
+; ((function_call
+; name: (_) @_vimcmd_identifier
+; arguments: (arguments (string content: _ @query) .))
+; (#eq? @_vimcmd_identifier "vim.treesitter.query.set_query"))
+
+; ;; highlight string as query if starts with `;; query`
+; ((string ("string_content") @query) (#lua-match? @query "^%s*;+%s?query"))
+
+; (comment) @comment
diff --git a/runtime/queries/vim/highlights.scm b/runtime/queries/vim/highlights.scm
new file mode 100644
index 0000000000..3d1729b2cd
--- /dev/null
+++ b/runtime/queries/vim/highlights.scm
@@ -0,0 +1,259 @@
+(identifier) @variable
+((identifier) @constant
+ (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
+
+;; Keywords
+
+[
+ "if"
+ "else"
+ "elseif"
+ "endif"
+] @conditional
+
+[
+ "try"
+ "catch"
+ "finally"
+ "endtry"
+ "throw"
+] @exception
+
+[
+ "for"
+ "endfor"
+ "in"
+ "while"
+ "endwhile"
+ "break"
+ "continue"
+] @repeat
+
+[
+ "function"
+ "endfunction"
+] @keyword.function
+
+;; Function related
+(function_declaration name: (_) @function)
+(call_expression function: (identifier) @function)
+(parameters (identifier) @parameter)
+(default_parameter (identifier) @parameter)
+
+[ (bang) (spread) ] @punctuation.special
+
+[ (no_option) (inv_option) (default_option) (option_name) ] @variable.builtin
+[
+ (scope)
+ "a:"
+ "$"
+] @namespace
+
+;; Commands and user defined commands
+
+[
+ "let"
+ "unlet"
+ "const"
+ "call"
+ "execute"
+ "normal"
+ "set"
+ "setlocal"
+ "silent"
+ "echo"
+ "echomsg"
+ "autocmd"
+ "augroup"
+ "return"
+ "syntax"
+ "lua"
+ "ruby"
+ "perl"
+ "python"
+ "highlight"
+ "command"
+ "delcommand"
+ "comclear"
+ "colorscheme"
+ "startinsert"
+ "stopinsert"
+ "global"
+ "runtime"
+ "wincmd"
+ "cnext"
+ "cprevious"
+ "cNext"
+ "vertical"
+ "leftabove"
+ "aboveleft"
+ "rightbelow"
+ "belowright"
+ "topleft"
+ "botright"
+ (unknown_command_name)
+ "edit"
+ "enew"
+ "find"
+ "ex"
+ "visual"
+ "view"
+] @keyword
+(map_statement cmd: _ @keyword)
+(command_name) @function.macro
+
+;; Syntax command
+
+(syntax_statement (keyword) @string)
+(syntax_statement [
+ "enable"
+ "on"
+ "off"
+ "reset"
+ "case"
+ "spell"
+ "foldlevel"
+ "iskeyword"
+ "keyword"
+ "match"
+ "cluster"
+ "region"
+] @keyword)
+
+(syntax_argument name: _ @keyword)
+
+[
+ "<buffer>"
+ "<nowait>"
+ "<silent>"
+ "<script>"
+ "<expr>"
+ "<unique>"
+] @constant.builtin
+
+(augroup_name) @namespace
+
+(au_event) @constant
+(normal_statement (commands) @constant)
+
+;; Highlight command
+
+(hl_attribute
+ key: _ @property
+ val: _ @constant)
+
+(hl_group) @type
+
+(highlight_statement [
+ "default"
+ "link"
+ "clear"
+] @keyword)
+
+;; Command command
+
+(command) @string
+
+(command_attribute
+ name: _ @property
+ val: (behavior
+ name: _ @constant
+ val: (identifier)? @function)?)
+
+;; Edit command
+(plus_plus_opt
+ val: _? @constant) @property
+(plus_cmd "+" @property) @property
+
+;; Runtime command
+
+(runtime_statement (where) @keyword.operator)
+
+;; Colorscheme command
+
+(colorscheme_statement (name) @string)
+
+;; Literals
+
+(string_literal) @string @spell
+(integer_literal) @number
+(float_literal) @float
+(comment) @comment @spell
+(pattern) @string.special
+(pattern_multi) @string.regex
+(filename) @string
+(heredoc (body) @string)
+((heredoc (parameter) @keyword))
+((scoped_identifier
+ (scope) @_scope . (identifier) @boolean)
+ (#eq? @_scope "v:")
+ (#any-of? @boolean "true" "false"))
+
+;; Operators
+
+[
+ "||"
+ "&&"
+ "&"
+ "+"
+ "-"
+ "*"
+ "/"
+ "%"
+ ".."
+ "is"
+ "isnot"
+ "=="
+ "!="
+ ">"
+ ">="
+ "<"
+ "<="
+ "=~"
+ "!~"
+ "="
+ "+="
+ "-="
+ "*="
+ "/="
+ "%="
+ ".="
+ "..="
+] @operator
+
+; Some characters have different meanings based on the context
+(unary_operation "!" @operator)
+(binary_operation "." @operator)
+
+;; Punctuation
+
+[
+ "("
+ ")"
+ "{"
+ "}"
+ "["
+ "]"
+] @punctuation.bracket
+
+(field_expression "." @punctuation.delimiter)
+
+[
+ ","
+ ":"
+] @punctuation.delimiter
+
+(ternary_expression ["?" ":"] @conditional)
+
+; Options
+((set_value) @number
+ (#match? @number "^[0-9]+(\.[0-9]+)?$"))
+
+((set_item
+ option: (option_name) @_option
+ value: (set_value) @function)
+ (#any-of? @_option
+ "tagfunc" "tfu"
+ "completefunc" "cfu"
+ "omnifunc" "ofu"
+ "operatorfunc" "opfunc"))
diff --git a/runtime/queries/vim/injections.scm b/runtime/queries/vim/injections.scm
new file mode 100644
index 0000000000..e2dea8fe75
--- /dev/null
+++ b/runtime/queries/vim/injections.scm
@@ -0,0 +1,26 @@
+(lua_statement (script (body) @lua))
+(lua_statement (chunk) @lua)
+; (ruby_statement (script (body) @ruby))
+; (ruby_statement (chunk) @ruby)
+; (python_statement (script (body) @python))
+; (python_statement (chunk) @python)
+;; (perl_statement (script (body) @perl))
+;; (perl_statement (chunk) @perl)
+
+; (autocmd_statement (pattern) @regex)
+
+((set_item
+ option: (option_name) @_option
+ value: (set_value) @vim)
+ (#any-of? @_option
+ "includeexpr" "inex"
+ "printexpr" "pexpr"
+ "formatexpr" "fex"
+ "indentexpr" "inde"
+ "foldtext" "fdt"
+ "foldexpr" "fde"
+ "diffexpr" "dex"
+ "patchexpr" "pex"
+ "charconvert" "ccv"))
+
+; (comment) @comment
diff --git a/runtime/syntax/gdresource.vim b/runtime/syntax/gdresource.vim
new file mode 100644
index 0000000000..7e1a2513e2
--- /dev/null
+++ b/runtime/syntax/gdresource.vim
@@ -0,0 +1,65 @@
+" Vim syntax file for Godot resource (scenes)
+" Language: gdresource
+" Maintainer: Maxim Kim <habamax@gmail.com>
+" Filenames: *.tscn, *.tres
+" Website: https://github.com/habamax/vim-gdscript
+
+if exists("b:current_syntax")
+ finish
+endif
+
+let s:keepcpo = &cpo
+set cpo&vim
+
+syn match gdResourceNumber "\<0x\%(_\=\x\)\+\>"
+syn match gdResourceNumber "\<0b\%(_\=[01]\)\+\>"
+syn match gdResourceNumber "\<\d\%(_\=\d\)*\>"
+syn match gdResourceNumber "\<\d\%(_\=\d\)*\%(e[+-]\=\d\%(_\=\d\)*\)\=\>"
+syn match gdResourceNumber "\<\d\%(_\=\d\)*\.\%(e[+-]\=\d\%(_\=\d\)*\)\=\%(\W\|$\)\@="
+syn match gdResourceNumber "\%(^\|\W\)\@1<=\%(\d\%(_\=\d\)*\)\=\.\d\%(_\=\d\)*\%(e[+-]\=\d\%(_\=\d\)*\)\=\>"
+
+syn keyword gdResourceKeyword true false
+
+syn region gdResourceString
+ \ start=+[uU]\="+ end='"' skip='\\\\\|\\"'
+ \ contains=@Spell keepend
+
+" Section
+syn region gdResourceSection matchgroup=gdResourceSectionDelimiter
+ \ start='^\[' end=']\s*$'
+ \ oneline keepend
+ \ contains=gdResourceSectionName,gdResourceSectionAttribute
+
+syn match gdResourceSectionName '\[\@<=\S\+' contained skipwhite
+syn match gdResourceSectionAttribute '\S\+\s*=\s*\S\+'
+ \ skipwhite keepend contained
+ \ contains=gdResourceSectionAttributeName,gdResourceSectionAttributeValue
+syn match gdResourceSectionAttributeName '\S\+\ze\(\s*=\)' skipwhite contained
+syn match gdResourceSectionAttributeValue '\(=\s*\)\zs\S\+\ze' skipwhite
+ \ contained
+ \ contains=gdResourceString,gdResourceNumber,gdResourceKeyword
+
+
+" Section body
+syn match gdResourceAttribute '^\s*\S\+\s*=.*$'
+ \ skipwhite keepend
+ \ contains=gdResourceAttributeName,gdResourceAttributeValue
+
+syn match gdResourceAttributeName '\S\+\ze\(\s*=\)' skipwhite contained
+syn match gdResourceAttributeValue '\(=\s*\)\zs.*$' skipwhite
+ \ contained
+ \ contains=gdResourceString,gdResourceNumber,gdResourceKeyword
+
+
+hi def link gdResourceNumber Constant
+hi def link gdResourceKeyword Constant
+hi def link gdResourceSectionName Statement
+hi def link gdResourceSectionDelimiter Delimiter
+hi def link gdResourceSectionAttributeName Type
+hi def link gdResourceAttributeName Identifier
+hi def link gdResourceString String
+
+let b:current_syntax = "gdresource"
+
+let &cpo = s:keepcpo
+unlet s:keepcpo
diff --git a/runtime/syntax/gdscript.vim b/runtime/syntax/gdscript.vim
new file mode 100644
index 0000000000..e9295a411d
--- /dev/null
+++ b/runtime/syntax/gdscript.vim
@@ -0,0 +1,105 @@
+" Vim syntax file for Godot gdscript
+" Language: gdscript
+" Maintainer: Maxim Kim <habamax@gmail.com>
+" Website: https://github.com/habamax/vim-gdscript
+" Filenames: *.gd
+
+if exists("b:current_syntax")
+ finish
+endif
+
+let s:keepcpo = &cpo
+set cpo&vim
+
+syntax sync maxlines=100
+
+syn keyword gdscriptConditional if else elif match
+syn keyword gdscriptRepeat for while break continue
+
+syn keyword gdscriptOperator is as not and or in
+
+syn match gdscriptClass "\v<\u\w+>"
+syn match gdscriptConstant "\<[_A-Z]\+[0-9_A-Z]*\>"
+syn match gdscriptBlockStart ":\s*$"
+
+syn keyword gdscriptKeyword null self owner parent tool
+syn keyword gdscriptBoolean false true
+
+syn keyword gdscriptStatement remote master puppet remotesync mastersync puppetsync sync
+syn keyword gdscriptStatement return pass
+syn keyword gdscriptStatement static const enum
+syn keyword gdscriptStatement breakpoint assert
+syn keyword gdscriptStatement onready
+syn keyword gdscriptStatement class_name extends
+
+syn keyword gdscriptType void bool int float String contained
+
+syn keyword gdscriptStatement var nextgroup=gdscriptTypeDecl skipwhite
+syn keyword gdscriptStatement const nextgroup=gdscriptTypeDecl skipwhite
+syn match gdscriptTypeDecl "\h\w*\s*:\s*\h\w*" contains=gdscriptOperator,gdscriptType,gdscriptClass contained skipwhite
+syn match gdscriptTypeDecl "->\s*\h\w*" contains=gdscriptOperator,gdscriptType,gdscriptClass skipwhite
+
+syn keyword gdscriptStatement export nextgroup=gdscriptExportTypeDecl skipwhite
+syn match gdscriptExportTypeDecl "(.\{-}[,)]" contains=gdscriptOperator,gdscriptType,gdscriptClass contained skipwhite
+
+syn keyword gdscriptStatement setget nextgroup=gdscriptSetGet,gdscriptSetGetSeparator skipwhite
+syn match gdscriptSetGet "\h\w*" nextgroup=gdscriptSetGetSeparator display contained skipwhite
+syn match gdscriptSetGetSeparator "," nextgroup=gdscriptSetGet display contained skipwhite
+
+syn keyword gdscriptStatement class func signal nextgroup=gdscriptFunctionName skipwhite
+syn match gdscriptFunctionName "\h\w*" nextgroup=gdscriptFunctionParams display contained skipwhite
+syn match gdscriptFunctionParams "(.*)" contains=gdscriptTypeDecl display contained skipwhite
+
+syn match gdscriptNode "\$\h\w*\%(/\h\w*\)*"
+
+syn match gdscriptComment "#.*$" contains=@Spell,gdscriptTodo
+
+syn region gdscriptString matchgroup=gdscriptQuotes
+ \ start=+[uU]\=\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1"
+ \ contains=gdscriptEscape,@Spell
+
+syn region gdscriptString matchgroup=gdscriptTripleQuotes
+ \ start=+[uU]\=\z('''\|"""\)+ end="\z1" keepend
+ \ contains=gdscriptEscape,@Spell
+
+syn match gdscriptEscape +\\[abfnrtv'"\\]+ contained
+syn match gdscriptEscape "\\$"
+
+" Numbers
+syn match gdscriptNumber "\<0x\%(_\=\x\)\+\>"
+syn match gdscriptNumber "\<0b\%(_\=[01]\)\+\>"
+syn match gdscriptNumber "\<\d\%(_\=\d\)*\>"
+syn match gdscriptNumber "\<\d\%(_\=\d\)*\%(e[+-]\=\d\%(_\=\d\)*\)\=\>"
+syn match gdscriptNumber "\<\d\%(_\=\d\)*\.\%(e[+-]\=\d\%(_\=\d\)*\)\=\%(\W\|$\)\@="
+syn match gdscriptNumber "\%(^\|\W\)\@1<=\%(\d\%(_\=\d\)*\)\=\.\d\%(_\=\d\)*\%(e[+-]\=\d\%(_\=\d\)*\)\=\>"
+
+" XXX, TODO, etc
+syn keyword gdscriptTodo TODO XXX FIXME HACK NOTE BUG contained
+
+hi def link gdscriptStatement Statement
+hi def link gdscriptKeyword Keyword
+hi def link gdscriptConditional Conditional
+hi def link gdscriptBoolean Boolean
+hi def link gdscriptOperator Operator
+hi def link gdscriptRepeat Repeat
+hi def link gdscriptSetGet Function
+hi def link gdscriptFunctionName Function
+hi def link gdscriptClass Type
+hi def link gdscriptConstant Constant
+hi def link gdscriptBuiltinStruct Typedef
+hi def link gdscriptComment Comment
+hi def link gdscriptString String
+hi def link gdscriptQuotes String
+hi def link gdscriptTripleQuotes String
+hi def link gdscriptEscape Special
+hi def link gdscriptNode PreProc
+hi def link gdscriptType Type
+hi def link gdscriptNumber Number
+hi def link gdscriptBlockStart Special
+hi def link gdscriptTodo Todo
+
+
+let b:current_syntax = "gdscript"
+
+let &cpo = s:keepcpo
+unlet s:keepcpo
diff --git a/runtime/syntax/gdshader.vim b/runtime/syntax/gdshader.vim
new file mode 100644
index 0000000000..f0d9f7edd9
--- /dev/null
+++ b/runtime/syntax/gdshader.vim
@@ -0,0 +1,57 @@
+" Vim syntax file for Godot shading language
+" Language: gdshader
+" Maintainer: Maxim Kim <habamax@gmail.com>
+" Filenames: *.gdshader
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn keyword gdshaderConditional if else switch case default
+syn keyword gdshaderRepeat for while do
+syn keyword gdshaderStatement return discard
+syn keyword gdshaderBoolean true false
+
+syn keyword gdshaderKeyword shader_type render_mode
+syn keyword gdshaderKeyword in out inout
+syn keyword gdshaderKeyword lowp mediump highp
+syn keyword gdshaderKeyword uniform varying const
+syn keyword gdshaderKeyword flat smooth
+
+syn keyword gdshaderType float vec2 vec3 vec4
+syn keyword gdshaderType uint uvec2 uvec3 uvec4
+syn keyword gdshaderType int ivec2 ivec3 ivec4
+syn keyword gdshaderType void bool
+syn keyword gdshaderType bvec2 bvec3 bvec4
+syn keyword gdshaderType mat2 mat3 mat4
+syn keyword gdshaderType sampler2D isampler2D usampler2D samplerCube
+
+syn match gdshaderMember "\v<(\.)@<=[a-z_]+\w*>"
+syn match gdshaderBuiltin "\v<[A-Z_]+[A-Z0-9_]*>"
+syn match gdshaderFunction "\v<\w*>(\()@="
+
+syn match gdshaderNumber "\v<\d+(\.)@!>"
+syn match gdshaderFloat "\v<\d*\.\d+(\.)@!>"
+syn match gdshaderFloat "\v<\d*\.=\d+(e-=\d+)@="
+syn match gdshaderExponent "\v(\d*\.=\d+)@<=e-=\d+>"
+
+syn match gdshaderComment "\v//.*$" contains=@Spell
+syn region gdshaderComment start="/\*" end="\*/" contains=@Spell
+syn keyword gdshaderTodo TODO FIXME XXX NOTE BUG HACK OPTIMIZE containedin=gdshaderComment
+
+hi def link gdshaderConditional Conditional
+hi def link gdshaderRepeat Repeat
+hi def link gdshaderStatement Statement
+hi def link gdshaderBoolean Boolean
+hi def link gdshaderKeyword Keyword
+hi def link gdshaderMember Identifier
+hi def link gdshaderBuiltin Identifier
+hi def link gdshaderFunction Function
+hi def link gdshaderType Type
+hi def link gdshaderNumber Number
+hi def link gdshaderFloat Float
+hi def link gdshaderExponent Special
+hi def link gdshaderComment Comment
+hi def link gdshaderTodo Todo
+
+let b:current_syntax = "gdshader"
diff --git a/runtime/syntax/gitattributes.vim b/runtime/syntax/gitattributes.vim
new file mode 100644
index 0000000000..b6d997f45d
--- /dev/null
+++ b/runtime/syntax/gitattributes.vim
@@ -0,0 +1,63 @@
+" Vim syntax file
+" Language: git attributes
+" Maintainer: ObserverOfTime <chronobserver@disroot.org>
+" Filenames: .gitattributes, *.git/info/attributes
+" Last Change: 2022 Sep 09
+
+if exists('b:current_syntax')
+ finish
+endif
+
+let s:cpo_save = &cpoptions
+set cpoptions&vim
+
+" Comment
+syn keyword gitattributesTodo contained TODO FIXME XXX
+syn match gitattributesComment /^\s*#.*/ contains=gitattributesTodo
+
+" Pattern
+syn match gitattributesPattern /^\s*#\@!\(".\+"\|\S\+\)/ skipwhite
+ \ nextgroup=gitattributesAttrPrefixed,gitattributesAttrAssigned skipwhite
+ \ contains=gitattributesGlob,gitattributesRange,gitattributesSeparator
+syn match gitattributesGlob /\\\@1<![?*]/ contained
+syn match gitattributesRange /\\\@1<!\[.\{-}\]/ contained
+syn match gitattributesSeparator '/' contained
+
+" Attribute
+syn match gitattributesAttrPrefixed /[!-]\?[A-Za-z0-9_.][-A-Za-z0-9_.]*/
+ \ transparent contained skipwhite
+ \ nextgroup=gitattributesAttrPrefixed,gitattributesAttrAssigned
+ \ contains=gitattributesPrefix,gitattributesName
+syn match gitattributesAttrAssigned /[A-Za-z0-9_.][-A-Za-z0-9_.]*=\S\+/
+ \ transparent contained skipwhite
+ \ nextgroup=gitattributesAttrPrefixed,gitattributesAttrAssigned
+ \ contains=gitattributesName,gitattributesAssign,gitattributesBoolean,gitattributesString
+syn match gitattributesName /[A-Za-z0-9_.][-A-Za-z0-9_.]*/
+ \ contained nextgroup=gitattributesAssign
+syn match gitattributesPrefix /[!-]/ contained
+ \ nextgroup=gitAttributesName
+syn match gitattributesAssign '=' contained
+ \ nextgroup=gitattributesBoolean,gitattributesString
+syn match gitattributesString /=\@1<=\S\+/ contained
+syn keyword gitattributesBoolean true false contained
+
+" Macro
+syn match gitattributesMacro /^\s*\[attr\]\s*\S\+/
+ \ nextgroup=gitattributesAttribute skipwhite
+
+hi def link gitattributesAssign Operator
+hi def link gitattributesBoolean Boolean
+hi def link gitattributesComment Comment
+hi def link gitattributesGlob Special
+hi def link gitattributesMacro Define
+hi def link gitattributesName Identifier
+hi def link gitattributesPrefix SpecialChar
+hi def link gitattributesRange Special
+hi def link gitattributesSeparator Delimiter
+hi def link gitattributesString String
+hi def link gitattributesTodo Todo
+
+let b:current_syntax = 'gitattributes'
+
+let &cpoptions = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/syntax/gitignore.vim b/runtime/syntax/gitignore.vim
new file mode 100644
index 0000000000..8e6d098acd
--- /dev/null
+++ b/runtime/syntax/gitignore.vim
@@ -0,0 +1,29 @@
+" Vim syntax file
+" Language: git ignore
+" Maintainer: ObserverOfTime <chronobserver@disroot.org>
+" Filenames: .gitignore, *.git/info/exclude
+" Last Change: 2022 Sep 10
+
+if exists('b:current_syntax')
+ finish
+endif
+
+" Comment
+syn keyword gitignoreTodo contained TODO FIXME XXX
+syn match gitignoreComment /^#.*/ contains=gitignoreTodo
+
+" Pattern
+syn match gitignorePattern /^#\@!.*$/ contains=gitignoreNegation,gitignoreGlob,gitignoreRange,gitignoreSeparator
+syn match gitignoreNegation /^!/ contained
+syn match gitignoreGlob /\\\@1<![?*]/ contained
+syn match gitignoreRange /\\\@1<!\[.\{-}\]/ contained
+syn match gitignoreSeparator '/' contained
+
+hi def link gitignoreComment Comment
+hi def link gitignoreGlob Special
+hi def link gitignoreNegation SpecialChar
+hi def link gitignoreRange Special
+hi def link gitignoreSeparator Delimiter
+hi def link gitignoreTodo Todo
+
+let b:current_syntax = 'gitignore'
diff --git a/runtime/syntax/lua.vim b/runtime/syntax/lua.vim
index b398e2e5c6..437a1ff113 100644
--- a/runtime/syntax/lua.vim
+++ b/runtime/syntax/lua.vim
@@ -1,11 +1,11 @@
" Vim syntax file
-" Language: Lua 4.0, Lua 5.0, Lua 5.1 and Lua 5.2
-" Maintainer: Marcus Aurelius Farias <masserahguard-lua 'at' yahoo com>
-" First Author: Carlos Augusto Teixeira Mendes <cmendes 'at' inf puc-rio br>
-" Last Change: 2022 Mar 31
-" Options: lua_version = 4 or 5
-" lua_subversion = 0 (4.0, 5.0) or 1 (5.1) or 2 (5.2)
-" default 5.2
+" Language: Lua 4.0, Lua 5.0, Lua 5.1 and Lua 5.2
+" Maintainer: Marcus Aurelius Farias <masserahguard-lua 'at' yahoo com>
+" First Author: Carlos Augusto Teixeira Mendes <cmendes 'at' inf puc-rio br>
+" Last Change: 2022 Mar 31
+" Options: lua_version = 4 or 5
+" lua_subversion = 0 (4.0, 5.0) or 1 (5.1) or 2 (5.2)
+" default 5.2
" quit when a syntax file was already loaded
if exists("b:current_syntax")
@@ -33,11 +33,11 @@ syn sync minlines=100
syn keyword luaTodo contained TODO FIXME XXX
syn match luaComment "--.*$" contains=luaTodo,@Spell
if lua_version == 5 && lua_subversion == 0
- syn region luaComment matchgroup=luaComment start="--\[\[" end="\]\]" contains=luaTodo,luaInnerComment,@Spell
+ syn region luaComment matchgroup=luaCommentDelimiter start="--\[\[" end="\]\]" contains=luaTodo,luaInnerComment,@Spell
syn region luaInnerComment contained transparent start="\[\[" end="\]\]"
elseif lua_version > 5 || (lua_version == 5 && lua_subversion >= 1)
" Comments in Lua 5.1: --[[ ... ]], [=[ ... ]=], [===[ ... ]===], etc.
- syn region luaComment matchgroup=luaComment start="--\[\z(=*\)\[" end="\]\z1\]" contains=luaTodo,@Spell
+ syn region luaComment matchgroup=luaCommentDelimiter start="--\[\z(=*\)\[" end="\]\z1\]" contains=luaTodo,@Spell
endif
" First line may start with #!
@@ -99,18 +99,18 @@ if lua_version < 5
elseif lua_version == 5
if lua_subversion == 0
syn match luaSpecial contained #\\[\\abfnrtv'"[\]]\|\\[[:digit:]]\{,3}#
- syn region luaString2 matchgroup=luaString start=+\[\[+ end=+\]\]+ contains=luaString2,@Spell
+ syn region luaString2 matchgroup=luaStringDelimiter start=+\[\[+ end=+\]\]+ contains=luaString2,@Spell
else
if lua_subversion == 1
syn match luaSpecial contained #\\[\\abfnrtv'"]\|\\[[:digit:]]\{,3}#
else " Lua 5.2
syn match luaSpecial contained #\\[\\abfnrtvz'"]\|\\x[[:xdigit:]]\{2}\|\\[[:digit:]]\{,3}#
endif
- syn region luaString2 matchgroup=luaString start="\[\z(=*\)\[" end="\]\z1\]" contains=@Spell
+ syn region luaString2 matchgroup=luaStringDelimiter start="\[\z(=*\)\[" end="\]\z1\]" contains=@Spell
endif
endif
-syn region luaString start=+'+ end=+'+ skip=+\\\\\|\\'+ contains=luaSpecial,@Spell
-syn region luaString start=+"+ end=+"+ skip=+\\\\\|\\"+ contains=luaSpecial,@Spell
+syn region luaString matchgroup=luaStringDelimiter start=+'+ end=+'+ skip=+\\\\\|\\'+ contains=luaSpecial,@Spell
+syn region luaString matchgroup=luaStringDelimiter start=+"+ end=+"+ skip=+\\\\\|\\"+ contains=luaSpecial,@Spell
" integer number
syn match luaNumber "\<\d\+\>"
@@ -333,27 +333,29 @@ endif
" Define the default highlighting.
" Only when an item doesn't have highlighting yet
-hi def link luaStatement Statement
-hi def link luaRepeat Repeat
-hi def link luaFor Repeat
-hi def link luaString String
-hi def link luaString2 String
-hi def link luaNumber Number
-hi def link luaOperator Operator
-hi def link luaIn Operator
-hi def link luaConstant Constant
-hi def link luaCond Conditional
-hi def link luaElse Conditional
-hi def link luaFunction Function
-hi def link luaComment Comment
-hi def link luaTodo Todo
-hi def link luaTable Structure
-hi def link luaError Error
-hi def link luaParenError Error
-hi def link luaBraceError Error
-hi def link luaSpecial SpecialChar
-hi def link luaFunc Identifier
-hi def link luaLabel Label
+hi def link luaStatement Statement
+hi def link luaRepeat Repeat
+hi def link luaFor Repeat
+hi def link luaString String
+hi def link luaString2 String
+hi def link luaStringDelimiter luaString
+hi def link luaNumber Number
+hi def link luaOperator Operator
+hi def link luaIn Operator
+hi def link luaConstant Constant
+hi def link luaCond Conditional
+hi def link luaElse Conditional
+hi def link luaFunction Function
+hi def link luaComment Comment
+hi def link luaCommentDelimiter luaComment
+hi def link luaTodo Todo
+hi def link luaTable Structure
+hi def link luaError Error
+hi def link luaParenError Error
+hi def link luaBraceError Error
+hi def link luaSpecial SpecialChar
+hi def link luaFunc Identifier
+hi def link luaLabel Label
let b:current_syntax = "lua"
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/racket.vim b/runtime/syntax/racket.vim
new file mode 100644
index 0000000000..b1ed2b454c
--- /dev/null
+++ b/runtime/syntax/racket.vim
@@ -0,0 +1,656 @@
+" Vim syntax file
+" Language: Racket
+" Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com>
+" Previous Maintainer: Will Langstroth <will@langstroth.com>
+" URL: https://github.com/benknoble/vim-racket
+" Description: Contains all of the keywords in #lang racket
+" Last Change: 2022 Aug 12
+
+" Initializing:
+if exists("b:current_syntax")
+ finish
+endif
+
+" Highlight unmatched parens
+syntax match racketError ,[]})],
+
+if version < 800
+ set iskeyword=33,35-39,42-58,60-90,94,95,97-122,126,_
+else
+ " syntax iskeyword 33,35-39,42-58,60-90,94,95,97-122,126,_
+ " converted from decimal to char
+ " :s/\d\+/\=submatch(0)->str2nr()->nr2char()/g
+ " but corrected to remove duplicate _, move ^ to end
+ syntax iskeyword @,!,#-',*-:,<-Z,a-z,~,_,^
+ " expanded
+ " syntax iskeyword !,#,$,%,&,',*,+,,,-,.,/,0-9,:,<,=,>,?,@,A-Z,_,a-z,~,^
+endif
+
+" Forms in order of appearance at
+" http://docs.racket-lang.org/reference/index.html
+"
+syntax keyword racketSyntax module module* module+ require provide quote
+syntax keyword racketSyntax #%datum #%expression #%top #%variable-reference #%app
+syntax keyword racketSyntax lambda case-lambda let let* letrec
+syntax keyword racketSyntax let-values let*-values let-syntax letrec-syntax
+syntax keyword racketSyntax let-syntaxes letrec-syntaxes letrec-syntaxes+values
+syntax keyword racketSyntax local shared
+syntax keyword racketSyntax if cond and or case define else =>
+syntax keyword racketSyntax define define-values define-syntax define-syntaxes
+syntax keyword racketSyntax define-for-syntax define-require-syntax define-provide-syntax
+syntax keyword racketSyntax define-syntax-rule
+syntax keyword racketSyntax define-record-type
+syntax keyword racketSyntax begin begin0
+syntax keyword racketSyntax begin-for-syntax
+syntax keyword racketSyntax when unless
+syntax keyword racketSyntax set! set!-values
+syntax keyword racketSyntax for for/list for/vector for/hash for/hasheq for/hasheqv
+syntax keyword racketSyntax for/and for/or for/lists for/first
+syntax keyword racketSyntax for/last for/fold
+syntax keyword racketSyntax for* for*/list for*/vector for*/hash for*/hasheq for*/hasheqv
+syntax keyword racketSyntax for*/and for*/or for*/lists for*/first
+syntax keyword racketSyntax for*/last for*/fold
+syntax keyword racketSyntax for/fold/derived for*/fold/derived
+syntax keyword racketSyntax define-sequence-syntax :do-in do
+syntax keyword racketSyntax with-continuation-mark
+syntax keyword racketSyntax quasiquote unquote unquote-splicing quote-syntax
+syntax keyword racketSyntax #%top-interaction
+syntax keyword racketSyntax define-package open-package package-begin
+syntax keyword racketSyntax define* define*-values define*-syntax define*-syntaxes open*-package
+syntax keyword racketSyntax package? package-exported-identifiers package-original-identifiers
+syntax keyword racketSyntax block #%stratified-body
+
+" 8 Contracts
+" 8.2 Function contracts
+syntax keyword racketSyntax -> ->* ->i ->d case-> dynamic->* unconstrained-domain->
+
+" 8.6.1 Nested Contract Boundaries
+syntax keyword racketSyntax with-contract define/contract define-struct/contract
+syntax keyword racketSyntax invariant-assertion current-contract-region
+
+" 9 Pattern Matching
+syntax keyword racketSyntax match match* match/values define/match
+syntax keyword racketSyntax match-lambda match-lambda* match-lambda**
+syntax keyword racketSyntax match-let match-let* match-let-values match-let*-values
+syntax keyword racketSyntax match-letrec match-define match-define-values
+
+" 10.2.3 Handling Exceptions
+syntax keyword racketSyntax with-handlers with-handlers*
+
+" 10.4 Continuations
+syntax keyword racketSyntax let/cc let/ec
+
+" 10.4.1 Additional Control Operators
+syntax keyword racketSyntax % prompt control prompt-at control-at reset shift
+syntax keyword racketSyntax reset-at shift-at prompt0 reset0 control0 shift0
+syntax keyword racketSyntax prompt0-at reset0-at control0-at shift0-at
+syntax keyword racketSyntax set cupto
+
+" 11.3.2 Parameters
+syntax keyword racketSyntax parameterize parameterize*
+
+" 12.5 Writing
+syntax keyword racketSyntax write display displayln print
+syntax keyword racketSyntax fprintf printf eprintf format
+syntax keyword racketSyntax print-pair-curly-braces print-mpair-curly-braces print-unreadable
+syntax keyword racketSyntax print-graph print-struct print-box print-vector-length print-hash-table
+syntax keyword racketSyntax print-boolean-long-form print-reader-abbreviations print-as-expression print-syntax-width
+syntax keyword racketSyntax current-write-relative-directory port-write-handler port-display-handler
+syntax keyword racketSyntax port-print-handler global-port-print-handler
+
+" 13.7 Custodians
+syntax keyword racketSyntax custodian? custodian-memory-accounting-available? custodian-box?
+syntax keyword racketSyntax make-custodian custodian-shutdown-all current-custodian custodian-managed-list
+syntax keyword racketSyntax custodian-require-memory custodian-limit-memory
+syntax keyword racketSyntax make-custodian-box custodian-box-value
+
+" lambda sign
+syntax match racketSyntax /\<[\u03bb]\>/
+
+
+" Functions ==================================================================
+
+syntax keyword racketFunc boolean? not equal? eqv? eq? equal?/recur immutable?
+syntax keyword racketFunc true false symbol=? boolean=? false?
+syntax keyword racketFunc number? complex? real? rational? integer?
+syntax keyword racketFunc exact-integer? exact-nonnegative-integer?
+syntax keyword racketFunc exact-positive-integer? inexact-real?
+syntax keyword racketFunc fixnum? flonum? zero? positive? negative?
+syntax keyword racketFunc even? odd? exact? inexact?
+syntax keyword racketFunc inexact->exact exact->inexact
+
+" 3.2.2 General Arithmetic
+
+" 3.2.2.1 Arithmetic
+syntax keyword racketFunc + - * / quotient remainder quotient/remainder modulo
+syntax keyword racketFunc add1 sub1 abs max min gcd lcm round exact-round floor
+syntax keyword racketFunc ceiling truncate numerator denominator rationalize
+
+" 3.2.2.2 Number Comparison
+syntax keyword racketFunc = < <= > >=
+
+" 3.2.2.3 Powers and Roots
+syntax keyword racketFunc sqrt integer-sqrt integer-sqrt/remainder
+syntax keyword racketFunc expt exp log
+
+" 3.2.2.3 Trigonometric Functions
+syntax keyword racketFunc sin cos tan asin acos atan
+
+" 3.2.2.4 Complex Numbers
+syntax keyword racketFunc make-rectangular make-polar
+syntax keyword racketFunc real-part imag-part magnitude angle
+syntax keyword racketFunc bitwise-ior bitwise-and bitwise-xor bitwise-not
+syntax keyword racketFunc bitwise-bit-set? bitwise-bit-field arithmetic-shift
+syntax keyword racketFunc integer-length
+
+" 3.2.2.5 Random Numbers
+syntax keyword racketFunc random random-seed
+syntax keyword racketFunc make-pseudo-random-generator pseudo-random-generator?
+syntax keyword racketFunc current-pseudo-random-generator pseudo-random-generator->vector
+syntax keyword racketFunc vector->pseudo-random-generator vector->pseudo-random-generator!
+
+" 3.2.2.8 Number-String Conversions
+syntax keyword racketFunc number->string string->number real->decimal-string
+syntax keyword racketFunc integer->integer-bytes
+syntax keyword racketFunc floating-point-bytes->real real->floating-point-bytes
+syntax keyword racketFunc system-big-endian?
+
+" 3.2.2.9 Extra Constants and Functions
+syntax keyword racketFunc pi sqr sgn conjugate sinh cosh tanh order-of-magnitude
+
+" 3.2.3 Flonums
+
+" 3.2.3.1 Flonum Arithmetic
+syntax keyword racketFunc fl+ fl- fl* fl/ flabs
+syntax keyword racketFunc fl= fl< fl> fl<= fl>= flmin flmax
+syntax keyword racketFunc flround flfloor flceiling fltruncate
+syntax keyword racketFunc flsin flcos fltan flasin flacos flatan
+syntax keyword racketFunc fllog flexp flsqrt
+syntax keyword racketFunc ->fl fl->exact-integer make-flrectangular
+syntax keyword racketFunc flreal-part flimag-part
+
+" 3.2.3.2 Flonum Vectors
+syntax keyword racketFunc flvector? flvector make-flvector flvector-length
+syntax keyword racketFunc flvector-ref flvector-set! flvector-copy in-flvector
+syntax keyword racketFunc shared-flvector make-shared-flvector
+syntax keyword racketSyntax for/flvector for*/flvector
+
+" 3.2.4 Fixnums
+syntax keyword racketFunc fx+ fx- fx* fxquotient fxremainder fxmodulo fxabs
+syntax keyword racketFunc fxand fxior fxxor fxnot fxlshift fxrshift
+syntax keyword racketFunc fx= fx< fx> fx<= fx>= fxmin fxmax fx->fl fl->fx
+
+" 3.2.4.2 Fixnum Vectors
+syntax keyword racketFunc fxvector? fxvector make-fxvector fxvector-length
+syntax keyword racketFunc fxvector-ref fxvector-set! fxvector-copy in-fxvector
+syntax keyword racketFunc for/fxvector for*/fxvector
+syntax keyword racketFunc shared-fxvector make-shared-fxvector
+
+" 3.3 Strings
+syntax keyword racketFunc string? make-string string string->immutable-string string-length
+syntax keyword racketFunc string-ref string-set! substring string-copy string-copy!
+syntax keyword racketFunc string-fill! string-append string->list list->string
+syntax keyword racketFunc build-string string=? string<? string<=? string>? string>=?
+syntax keyword racketFunc string-ci=? string-ci<? string-ci<=? string-ci>? string-ci>=?
+syntax keyword racketFunc string-upcase string-downcase string-titlecase string-foldcase
+syntax keyword racketFunc string-normalize-nfd string-normalize-nfc string-normalize-nfkc
+syntax keyword racketFunc string-normalize-spaces string-trim
+syntax keyword racketFunc string-locale=? string-locale>? string-locale<?
+syntax keyword racketFunc string-locale-ci=? string-locale<=?
+syntax keyword racketFunc string-locale-upcase string-locale-downcase
+syntax keyword racketFunc string-append* string-join
+
+" 3.4 Bytestrings
+syntax keyword racketFunc bytes? make-bytes bytes bytes->immutable-bytes byte?
+syntax keyword racketFunc bytes-length bytes-ref bytes-set! subbytes bytes-copy
+syntax keyword racketFunc bytes-copy! bytes-fill! bytes-append bytes->list list->bytes
+syntax keyword racketFunc make-shared-bytes shared-bytes
+syntax keyword racketFunc bytes=? bytes<? bytes>?
+syntax keyword racketFunc bytes->string/utf-8 bytes->string/latin-1
+syntax keyword racketFunc string->bytes/locale string->bytes/latin-1 string->bytes/utf-8
+syntax keyword racketFunc string-utf-8-length bytes-utf8-ref bytes-utf-8-index
+syntax keyword racketFunc bytes-open-converter bytes-close-converter
+syntax keyword racketFunc bytes-convert bytes-convert-end bytes-converter?
+syntax keyword racketFunc locale-string-encoding
+
+" 3.5 Characters
+syntax keyword racketFunc char? char->integer integer->char
+syntax keyword racketFunc char=? char<? char<=? char>? char>=?
+syntax keyword racketFunc char-ci=? char-ci<? char-ci<=? char-ci>? char-ci>=?
+syntax keyword racketFunc char-alphabetic? char-lower-case? char-upper-case? char-title-case?
+syntax keyword racketFunc char-numeric? char-symbolic? char-punctuation? char-graphic?
+syntax keyword racketFunc char-whitespace? char-blank?
+syntax keyword racketFunc char-iso-control? char-general-category
+syntax keyword racketFunc make-known-char-range-list
+syntax keyword racketFunc char-upcase char-downcase char-titlecase char-foldcase
+
+" 3.6 Symbols
+syntax keyword racketFunc symbol? symbol-interned? symbol-unreadable?
+syntax keyword racketFunc symbol->string string->symbol
+syntax keyword racketFunc string->uninterned-symbol string->unreadable-symbol
+syntax keyword racketFunc gensym
+
+" 3.7 Regular Expressions
+syntax keyword racketFunc regexp? pregexp? byte-regexp? byte-pregexp?
+syntax keyword racketFunc regexp pregexp byte-regexp byte-pregexp
+syntax keyword racketFunc regexp-quote regexp-match regexp-match*
+syntax keyword racketFunc regexp-try-match regexp-match-positions
+syntax keyword racketFunc regexp-match-positions* regexp-match?
+syntax keyword racketFunc regexp-match-peek-positions regexp-match-peek-immediate
+syntax keyword racketFunc regexp-match-peek regexp-match-peek-positions*
+syntax keyword racketFunc regexp-match/end regexp-match-positions/end
+syntax keyword racketFunc regexp-match-peek-positions-immediat/end
+syntax keyword racketFunc regexp-split regexp-replace regexp-replace*
+syntax keyword racketFunc regexp-replace-quote
+
+" 3.8 Keywords
+syntax keyword racketFunc keyword? keyword->string string->keyword keyword<?
+
+" 3.9 Pairs and Lists
+syntax keyword racketFunc pair? null? cons car cdr null
+syntax keyword racketFunc list? list list* build-list length
+syntax keyword racketFunc list-ref list-tail append reverse map andmap ormap
+syntax keyword racketFunc for-each foldl foldr filter remove remq remv remove*
+syntax keyword racketFunc remq* remv* sort member memv memq memf
+syntax keyword racketFunc findf assoc assv assq assf
+syntax keyword racketFunc caar cadr cdar cddr caaar caadr cadar caddr cdaar
+syntax keyword racketFunc cddar cdddr caaaar caaadr caadar caaddr cadadr caddar
+syntax keyword racketFunc cadddr cdaaar cdaadr cdadar cddaar cdddar cddddr
+
+" 3.9.7 Additional List Functions and Synonyms
+" (require racket/list)
+syntax keyword racketFunc empty cons? empty? first rest
+syntax keyword racketFunc second third fourth fifth sixth seventh eighth ninth tenth
+syntax keyword racketFunc last last-pair make-list take drop split-at
+syntax keyword racketFunc take-right drop-right split-at-right add-between
+syntax keyword racketFunc append* flatten remove-duplicates filter-map
+syntax keyword racketFunc count partition append-map filter-not shuffle
+syntax keyword racketFunc argmin argmax make-reader-graph placeholder? make-placeholder
+syntax keyword racketFunc placeholder-set! placeholder-get hash-placeholder?
+syntax keyword racketFunc make-hash-placeholder make-hasheq-placeholder
+syntax keyword racketFunc make-hasheqv-placeholder make-immutable-hasheqv
+
+" 3.10 Mutable Pairs and Lists
+syntax keyword racketFunc mpair? mcons mcar mcdr
+
+" 3.11 Vectors
+syntax keyword racketFunc vector? make-vector vector vector-immutable vector-length
+syntax keyword racketFunc vector-ref vector-set! vector->list list->vector
+syntax keyword racketFunc vector->immutable-vector vector-fill! vector-copy!
+syntax keyword racketFunc vector->values build-vector vector-set*! vector-map
+syntax keyword racketFunc vector-map! vector-append vector-take vector-take-right
+syntax keyword racketFunc vector-drop vector-drop-right vector-split-at
+syntax keyword racketFunc vector-split-at-right vector-copy vector-filter
+syntax keyword racketFunc vector-filter-not vector-count vector-argmin vector-argmax
+syntax keyword racketFunc vector-member vector-memv vector-memq
+
+" 3.12 Boxes
+syntax keyword racketFunc box? box box-immutable unbox set-box!
+
+" 3.13 Hash Tables
+syntax keyword racketFunc hash? hash-equal? hash-eqv? hash-eq? hash-weak? hash
+syntax keyword racketFunc hasheq hasheqv
+syntax keyword racketFunc make-hash make-hasheqv make-hasheq make-weak-hash make-weak-hasheqv
+syntax keyword racketFunc make-weak-hasheq make-immutable-hash make-immutable-hasheqv
+syntax keyword racketFunc make-immutable-hasheq
+syntax keyword racketFunc hash-set! hash-set*! hash-set hash-set* hash-ref hash-ref!
+syntax keyword racketFunc hash-has-key? hash-update! hash-update hash-remove!
+syntax keyword racketFunc hash-remove hash-map hash-keys hash-values
+syntax keyword racketFunc hash->list hash-for-each hash-count
+syntax keyword racketFunc hash-iterate-first hash-iterate-next hash-iterate-key
+syntax keyword racketFunc hash-iterate-value hash-copy eq-hash-code eqv-hash-code
+syntax keyword racketFunc equal-hash-code equal-secondary-hash-code
+
+" 3.15 Dictionaries
+syntax keyword racketFunc dict? dict-mutable? dict-can-remove-keys? dict-can-functional-set?
+syntax keyword racketFunc dict-set! dict-set*! dict-set dict-set* dict-has-key? dict-ref
+syntax keyword racketFunc dict-ref! dict-update! dict-update dict-remove! dict-remove
+syntax keyword racketFunc dict-map dict-for-each dict-count dict-iterate-first dict-iterate-next
+syntax keyword racketFunc dict-iterate-key dict-iterate-value in-dict in-dict-keys
+syntax keyword racketFunc in-dict-values in-dict-pairs dict-keys dict-values
+syntax keyword racketFunc dict->list prop: dict prop: dict/contract dict-key-contract
+syntax keyword racketFunc dict-value-contract dict-iter-contract make-custom-hash
+syntax keyword racketFunc make-immutable-custom-hash make-weak-custom-hash
+
+" 3.16 Sets
+syntax keyword racketFunc set seteqv seteq set-empty? set-count set-member?
+syntax keyword racketFunc set-add set-remove set-union set-intersect set-subtract
+syntax keyword racketFunc set-symmetric-difference set=? subset? proper-subset?
+syntax keyword racketFunc set-map set-for-each set? set-equal? set-eqv? set-eq?
+syntax keyword racketFunc set/c in-set for/set for/seteq for/seteqv for*/set
+syntax keyword racketFunc for*/seteq for*/seteqv list->set list->seteq
+syntax keyword racketFunc list->seteqv set->list
+
+" 3.17 Procedures
+syntax keyword racketFunc procedure? apply compose compose1 procedure-rename procedure->method
+syntax keyword racketFunc keyword-apply procedure-arity procedure-arity?
+syntax keyword racketFunc procedure-arity-includes? procedure-reduce-arity
+syntax keyword racketFunc procedure-keywords make-keyword-procedure
+syntax keyword racketFunc procedure-reduce-keyword-arity procedure-struct-type?
+syntax keyword racketFunc procedure-extract-target checked-procedure-check-and-extract
+syntax keyword racketFunc primitive? primitive-closure? primitive-result-arity
+syntax keyword racketFunc identity const thunk thunk* negate curry curryr
+
+" 3.18 Void
+syntax keyword racketFunc void void?
+
+" 4.1 Defining Structure Types
+syntax keyword racketFunc struct struct-field-index define-struct define-struct define-struct/derived
+
+" 4.2 Creating Structure Types
+syntax keyword racketFunc make-struct-type make-struct-field-accessor make-struct-field-mutator
+
+" 4.3 Structure Type Properties
+syntax keyword racketFunc make-struct-type-property struct-type-property? struct-type-property-accessor-procedure?
+
+" 4.4 Copying and Updating Structures
+syntax keyword racketFunc struct-copy
+
+" 4.5 Structure Utilities
+syntax keyword racketFunc struct->vector struct? struct-type?
+syntax keyword racketFunc struct-constructor-procedure? struct-predicate-procedure? struct-accessor-procedure? struct-mutator-procedure?
+syntax keyword racketFunc prefab-struct-key make-prefab-struct prefab-key->struct-type
+
+" 4.6 Structure Type Transformer Binding
+syntax keyword racketFunc struct-info? check-struct-info? make-struct-info extract-struct-info
+syntax keyword racketFunc struct-auto-info? struct-auto-info-lists
+
+" 5.1 Creating Interfaces
+syntax keyword racketFunc interface interface*
+
+" 5.2 Creating Classes
+syntax keyword racketFunc class* class inspect
+syntax keyword racketFunc init init-field field inherit field init-rest
+syntax keyword racketFunc public public* pubment pubment* public-final public-final*
+syntax keyword racketFunc override override* overment overment* override-final override-final*
+syntax keyword racketFunc augride augride* augment augment* augment-final augment-final*
+syntax keyword racketFunc abstract inherit inherit/super inherit/inner
+syntax keyword racketFunc rename-inner rename-super
+syntax keyword racketFunc define/public define/pubment define/public-final
+syntax keyword racketFunc define/override define/overment define/override-final
+syntax keyword racketFunc define/augride define/augment define/augment-final
+syntax keyword racketFunc private* define/private
+
+" 5.2.3 Methods
+syntax keyword racketFunc class/derived
+syntax keyword racketFunc super inner define-local-member-name define-member-name
+syntax keyword racketFunc member-name-key generate-member-key member-name-key?
+syntax keyword racketFunc member-name-key=? member-name-key-hash-code
+
+" 5.3 Creating Objects
+syntax keyword racketFunc make-object instantiate new
+syntax keyword racketFunc super-make-object super-instantiate super-new
+
+"5.4 Field and Method Access
+syntax keyword racketFunc method-id send send/apply send/keyword-apply dynamic-send send*
+syntax keyword racketFunc get-field set-field! field-bound?
+syntax keyword racketFunc class-field-accessor class-field-mutator
+
+"5.4.3 Generics
+syntax keyword racketFunc generic send-generic make-generic
+
+" 8.1 Data-strucure contracts
+syntax keyword racketFunc flat-contract-with-explanation flat-named-contract
+" TODO where do any/c and none/c `value`s go?
+syntax keyword racketFunc or/c first-or/c and/c not/c =/c </c >/c <=/c >=/c
+syntax keyword racketFunc between/c real-in integer-in char-in natural-number/c
+syntax keyword racketFunc string-len/c printable/c one-of/c symbols vectorof
+syntax keyword racketFunc vector-immutableof vector/c box/c box-immutable/c listof
+syntax keyword racketFunc non-empty-listof list*of cons/c cons/dc list/c *list/c
+syntax keyword racketFunc syntax/c struct/c struct/dc parameter/c
+syntax keyword racketFunc procedure-arity-includes/c hash/c hash/dc channel/c
+syntax keyword racketFunc prompt-tag/c continuation-mark-key/c evt/c promise/c
+syntax keyword racketFunc flat-contract flat-contract-predicate suggest/c
+
+" 9.1 Multiple Values
+syntax keyword racketFunc values call-with-values
+
+" 10.2.2 Raising Exceptions
+syntax keyword racketFunc raise error raise-user-error raise-argument-error
+syntax keyword racketFunc raise-result-error raise-argument-error raise-range-error
+syntax keyword racketFunc raise-type-error raise-mismatch-error raise-arity-error
+syntax keyword racketFunc raise-syntax-error
+
+" 10.2.3 Handling Exceptions
+syntax keyword racketFunc call-with-exception-handler uncaught-exception-handler
+
+" 10.2.4 Configuring Default Handlers
+syntax keyword racketFunc error-escape-handler error-display-handler error-print-width
+syntax keyword racketFunc error-print-context-length error-values->string-handler
+syntax keyword racketFunc error-print-source-location
+
+" 10.2.5 Built-in Exception Types
+syntax keyword racketFunc exn exn:fail exn:fail:contract exn:fail:contract:arity
+syntax keyword racketFunc exn:fail:contract:divide-by-zero exn:fail:contract:non-fixnum-result
+syntax keyword racketFunc exn:fail:contract:continuation exn:fail:contract:variable
+syntax keyword racketFunc exn:fail:syntax exn:fail:syntax:unbound exn:fail:syntax:missing-module
+syntax keyword racketFunc exn:fail:read exn:fail:read:eof exn:fail:read:non-char
+syntax keyword racketFunc exn:fail:filesystem exn:fail:filesystem:exists
+syntax keyword racketFunc exn:fail:filesystem:version exn:fail:filesystem:errno
+syntax keyword racketFunc exn:fail:filesystem:missing-module
+syntax keyword racketFunc exn:fail:network exn:fail:network:errno exn:fail:out-of-memory
+syntax keyword racketFunc exn:fail:unsupported exn:fail:user
+syntax keyword racketFunc exn:break exn:break:hang-up exn:break:terminate
+
+" 10.3 Delayed Evaluation
+syntax keyword racketFunc promise? delay lazy force promise-forced? promise-running?
+
+" 10.3.1 Additional Promise Kinds
+syntax keyword racketFunc delay/name promise/name delay/strict delay/sync delay/thread delay/idle
+
+" 10.4 Continuations
+syntax keyword racketFunc call-with-continuation-prompt abort-current-continuation make-continuation-prompt-tag
+syntax keyword racketFunc default-continuation-prompt-tag call-with-current-continuation call/cc
+syntax keyword racketFunc call-with-composable-continuation call-with-escape-continuation call/ec
+syntax keyword racketFunc call-with-continuation-barrier continuation-prompt-available
+syntax keyword racketFunc continuation? continuation-prompt-tag dynamic-wind
+
+" 10.4.1 Additional Control Operators
+syntax keyword racketFunc call/prompt abort/cc call/comp abort fcontrol spawn splitter new-prompt
+
+" 11.3.2 Parameters
+syntax keyword racketFunc make-parameter make-derived-parameter parameter?
+syntax keyword racketFunc parameter-procedure=? current-parameterization
+syntax keyword racketFunc call-with-parameterization parameterization?
+
+" 14.1.1 Manipulating Paths
+syntax keyword racketFunc path? path-string? path-for-some-system? string->path path->string path->bytes
+syntax keyword racketFunc string->path-element bytes->path-element path-element->string path-element->bytes
+syntax keyword racketFunc path-convention-type system-path-convention-type build-type
+syntax keyword racketFunc build-type/convention-type
+syntax keyword racketFunc absolute-path? relative-path? complete-path?
+syntax keyword racketFunc path->complete-path path->directory-path
+syntax keyword racketFunc resolve-path cleanse-path expand-user-path simplify-path normal-case-path split-path
+syntax keyword racketFunc path-replace-suffix path-add-suffix
+
+" 14.1.2 More Path Utilities
+syntax keyword racketFunc explode-path file-name-from-path filename-extension find-relative-path normalize-path
+syntax keyword racketFunc path-element? path-only simple-form-path some-simple-path->string string->some-system-path
+
+" 15.6 Time
+syntax keyword racketFunc current-seconds current-inexact-milliseconds
+syntax keyword racketFunc seconds->date current-milliseconds
+
+
+syntax match racketDelimiter !\<\.\>!
+
+syntax cluster racketTop contains=racketSyntax,racketFunc,racketDelimiter
+
+syntax match racketConstant ,\<\*\k\+\*\>,
+syntax match racketConstant ,\<<\k\+>\>,
+
+" Non-quoted lists, and strings
+syntax region racketStruc matchgroup=racketParen start="("rs=s+1 end=")"re=e-1 contains=@racketTop
+syntax region racketStruc matchgroup=racketParen start="#("rs=s+2 end=")"re=e-1 contains=@racketTop
+syntax region racketStruc matchgroup=racketParen start="{"rs=s+1 end="}"re=e-1 contains=@racketTop
+syntax region racketStruc matchgroup=racketParen start="#{"rs=s+2 end="}"re=e-1 contains=@racketTop
+syntax region racketStruc matchgroup=racketParen start="\["rs=s+1 end="\]"re=e-1 contains=@racketTop
+syntax region racketStruc matchgroup=racketParen start="#\["rs=s+2 end="\]"re=e-1 contains=@racketTop
+
+for lit in ['hash', 'hasheq', 'hasheqv']
+ execute printf('syntax match racketLit "\<%s\>" nextgroup=@racketParen containedin=ALLBUT,.*String,.*Comment', '#'.lit)
+endfor
+
+for lit in ['rx', 'rx#', 'px', 'px#']
+ execute printf('syntax match racketRe "\<%s\>" nextgroup=@racketString containedin=ALLBUT,.*String,.*Comment,', '#'.lit)
+endfor
+
+unlet lit
+
+" Simple literals
+
+" Strings
+
+syntax match racketStringEscapeError "\\." contained display
+
+syntax match racketStringEscape "\\[abtnvfre'"\\]" contained display
+syntax match racketStringEscape "\\$" contained display
+syntax match racketStringEscape "\\\o\{1,3}\|\\x\x\{1,2}" contained display
+
+syntax match racketUStringEscape "\\u\x\{1,4}\|\\U\x\{1,8}" contained display
+syntax match racketUStringEscape "\\u\x\{4}\\u\x\{4}" contained display
+
+syntax region racketString start=/\%(\\\)\@<!"/ skip=/\\[\\"]/ end=/"/ contains=racketStringEscapeError,racketStringEscape,racketUStringEscape
+syntax region racketString start=/#"/ skip=/\\[\\"]/ end=/"/ contains=racketStringEscapeError,racketStringEscape
+
+if exists("racket_no_string_fold")
+ syn region racketString start=/#<<\z(.*\)$/ end=/^\z1$/
+else
+ syn region racketString start=/#<<\z(.*\)$/ end=/^\z1$/ fold
+endif
+
+
+syntax cluster racketTop add=racketError,racketConstant,racketStruc,racketString
+
+" Numbers
+
+" anything which doesn't match the below rules, but starts with a #d, #b, #o,
+" #x, #i, or #e, is an error
+syntax match racketNumberError "\<#[xdobie]\k*"
+
+syntax match racketContainedNumberError "\<#o\k*[^-+0-7delfinas#./@]\>"
+syntax match racketContainedNumberError "\<#b\k*[^-+01delfinas#./@]\>"
+syntax match racketContainedNumberError "\<#[ei]#[ei]"
+syntax match racketContainedNumberError "\<#[xdob]#[xdob]"
+
+" start with the simpler sorts
+syntax match racketNumber "\<\(#[dobie]\)\{0,2}[-+]\?\(\d\+\|\d\+#*\.\|\d*\.\d\+\)#*\(/\d\+#*\)\?\([sdlef][-+]\?\d\+#*\)\?\>" contains=racketContainedNumberError
+syntax match racketNumber "\<\(#[dobie]\)\{0,2}[-+]\?\d\+/\d\+\>" contains=racketContainedNumberError
+syntax match racketNumber "\<\(#[dobie]\)\{0,2}[-+]\?\d\+/\d\+[-+]\d\+\(/\d\+\)\?i\>" contains=racketContainedNumberError
+
+" different possible ways of expressing complex values
+syntax match racketNumber "\<\(#[dobie]\)\{0,2}[-+]\(\d\+\|\d\+#*\.\|\d*\.\d\+\)#*\(/\d\+#*\)\?\([sdlef][-+]\?\d\+#*\)\?i\>" contains=racketContainedNumberError
+syntax match racketNumber "\<\(#[dobie]\)\{0,2}[-+]\?\(\d\+\|\d\+#*\.\|\d*\.\d\+\)#*\(/\d\+#*\)\?\([sdlef][-+]\?\d\+#*\)\?[-+]\(\d\+\|\d\+#*\.\|\d*\.\d\+\)#*\(/\d\+#*\)\?\([sdlef][-+]\?\d\+#*\)\?i\>" contains=racketContainedNumberError
+syntax match racketNumber "\<\(#[dobie]\)\{0,2}[-+]\(inf\|nan\)\.[0f][-+]\(\d\+\|\d\+#*\.\|\d*\.\d\+\)#*\(/\d\+#*\)\?\([sdlef][-+]\?\d\+#*\)\?i\>" contains=racketContainedNumberError
+syntax match racketNumber "\<\(#[dobie]\)\{0,2}[-+]\?\(\d\+\|\d\+#*\.\|\d*\.\d\+\)#*\(/\d\+#*\)\?\([sdlef][-+]\?\d\+#*\)\?[-+]\(inf\|nan\)\.[0f]i\>" contains=racketContainedNumberError
+syntax match racketNumber "\<\(#[dobie]\)\{0,2}[-+]\?\(\d\+\|\d\+#*\.\|\d*\.\d\+\)#*\(/\d\+#*\)\?\([sdlef][-+]\?\d\+#*\)\?@[-+]\?\(\d\+\|\d\+#*\.\|\d*\.\d\+\)#*\(/\d\+#*\)\?\([sdlef][-+]\?\d\+#*\)\?\>" contains=racketContainedNumberError
+syntax match racketNumber "\<\(#[dobie]\)\{0,2}[-+]\(inf\|nan\)\.[0f]@[-+]\?\(\d\+\|\d\+#*\.\|\d*\.\d\+\)#*\(/\d\+#*\)\?\([sdlef][-+]\?\d\+#*\)\?\>" contains=racketContainedNumberError
+syntax match racketNumber "\<\(#[dobie]\)\{0,2}[-+]\?\(\d\+\|\d\+#*\.\|\d*\.\d\+\)#*\(/\d\+#*\)\?\([sdlef][-+]\?\d\+#*\)\?@[-+]\(inf\|nan\)\.[0f]\>" contains=racketContainedNumberError
+
+" hex versions of the above (separate because of the different possible exponent markers)
+syntax match racketNumber "\<\(#x\|#[ei]#x\|#x#[ei]\)[-+]\?\(\x\+\|\x\+#*\.\|\x*\.\x\+\)#*\(/\x\+#*\)\?\([sl][-+]\?\x\+#*\)\?\>"
+syntax match racketNumber "\<\(#x\|#[ei]#x\|#x#[ei]\)[-+]\?\x\+/\x\+\>"
+syntax match racketNumber "\<\(#x\|#[ei]#x\|#x#[ei]\)[-+]\?\x\+/\x\+[-+]\x\+\(/\x\+\)\?i\>"
+
+syntax match racketNumber "\<\(#x\|#[ei]#x\|#x#[ei]\)[-+]\(\x\+\|\x\+#*\.\|\x*\.\x\+\)#*\(/\x\+#*\)\?\([sl][-+]\?\x\+#*\)\?i\>"
+syntax match racketNumber "\<\(#x\|#[ei]#x\|#x#[ei]\)[-+]\?\(\x\+\|\x\+#*\.\|\x*\.\x\+\)#*\(/\x\+#*\)\?\([sl][-+]\?\x\+#*\)\?[-+]\(\x\+\|\x\+#*\.\|\x*\.\x\+\)#*\(/\x\+#*\)\?\([sl][-+]\?\x\+#*\)\?i\>"
+syntax match racketNumber "\<\(#x\|#[ei]#x\|#x#[ei]\)[-+]\(inf\|nan\)\.[0f][-+]\(\x\+\|\x\+#*\.\|\x*\.\x\+\)#*\(/\x\+#*\)\?\([sl][-+]\?\x\+#*\)\?i\>"
+syntax match racketNumber "\<\(#x\|#[ei]#x\|#x#[ei]\)[-+]\?\(\x\+\|\x\+#*\.\|\x*\.\x\+\)#*\(/\x\+#*\)\?\([sl][-+]\?\x\+#*\)\?[-+]\(inf\|nan\)\.[0f]i\>"
+syntax match racketNumber "\<\(#x\|#[ei]#x\|#x#[ei]\)[-+]\?\(\x\+\|\x\+#*\.\|\x*\.\x\+\)#*\(/\x\+#*\)\?\([sl][-+]\?\x\+#*\)\?@[-+]\?\(\x\+\|\x\+#*\.\|\x*\.\x\+\)#*\(/\x\+#*\)\?\([sl][-+]\?\x\+#*\)\?\>"
+syntax match racketNumber "\<\(#x\|#[ei]#x\|#x#[ei]\)[-+]\(inf\|nan\)\.[0f]@[-+]\?\(\x\+\|\x\+#*\.\|\x*\.\x\+\)#*\(/\x\+#*\)\?\([sl][-+]\?\x\+#*\)\?\>"
+syntax match racketNumber "\<\(#x\|#[ei]#x\|#x#[ei]\)[-+]\?\(\x\+\|\x\+#*\.\|\x*\.\x\+\)#*\(/\x\+#*\)\?\([sl][-+]\?\x\+#*\)\?@[-+]\(inf\|nan\)\.[0f]\>"
+
+" these work for any radix
+syntax match racketNumber "\<\(#[xdobie]\)\{0,2}[-+]\(inf\|nan\)\.[0f]i\?\>" contains=racketContainedNumberError
+syntax match racketNumber "\<\(#[xdobie]\)\{0,2}[-+]\(inf\|nan\)\.[0f][-+]\(inf\|nan\)\.[0f]i\>" contains=racketContainedNumberError
+syntax match racketNumber "\<\(#[xdobie]\)\{0,2}[-+]\(inf\|nan\)\.[0f]@[-+]\(inf\|nan\)\.[0f]\>" contains=racketContainedNumberError
+
+syntax keyword racketBoolean #t #f #true #false #T #F
+
+syntax match racketError "\<#\\\k*\>"
+
+syntax match racketChar "\<#\\.\w\@!"
+syntax match racketChar "\<#\\space\>"
+syntax match racketChar "\<#\\newline\>"
+syntax match racketChar "\<#\\return\>"
+syntax match racketChar "\<#\\null\?\>"
+syntax match racketChar "\<#\\backspace\>"
+syntax match racketChar "\<#\\tab\>"
+syntax match racketChar "\<#\\linefeed\>"
+syntax match racketChar "\<#\\vtab\>"
+syntax match racketChar "\<#\\page\>"
+syntax match racketChar "\<#\\rubout\>"
+syntax match racketChar "\<#\\\o\{1,3}\>"
+syntax match racketChar "\<#\\x\x\{1,2}\>"
+syntax match racketChar "\<#\\u\x\{1,6}\>"
+
+syntax cluster racketTop add=racketNumber,racketBoolean,racketChar
+
+" Command-line parsing
+syntax keyword racketExtFunc command-line current-command-line-arguments once-any help-labels multi once-each
+
+syntax match racketSyntax "#lang "
+syntax match racketExtSyntax "#:\k\+"
+
+syntax cluster racketTop add=racketExtFunc,racketExtSyntax
+
+" syntax quoting, unquoting and quasiquotation
+syntax match racketQuote "#\?['`]"
+
+syntax match racketUnquote "#,"
+syntax match racketUnquote "#,@"
+syntax match racketUnquote ","
+syntax match racketUnquote ",@"
+
+" Comments
+syntax match racketSharpBang "\%^#![ /].*" display
+syntax match racketComment /;.*$/ contains=racketTodo,racketNote,@Spell
+syntax region racketMultilineComment start=/#|/ end=/|#/ contains=racketMultilineComment,racketTodo,racketNote,@Spell
+syntax match racketFormComment "#;" nextgroup=@racketTop
+
+syntax match racketTodo /\C\<\(FIXME\|TODO\|XXX\)\ze:\?\>/ contained
+syntax match racketNote /\CNOTE\ze:\?/ contained
+
+syntax cluster racketTop add=racketQuote,racketUnquote,racketComment,racketMultilineComment,racketFormComment
+
+" Synchronization and the wrapping up...
+syntax sync match matchPlace grouphere NONE "^[^ \t]"
+" ... i.e. synchronize on a line that starts at the left margin
+
+" Define the default highlighting.
+highlight default link racketSyntax Statement
+highlight default link racketFunc Function
+
+highlight default link racketString String
+highlight default link racketStringEscape Special
+highlight default link racketUStringEscape Special
+highlight default link racketStringEscapeError Error
+highlight default link racketChar Character
+highlight default link racketBoolean Boolean
+
+highlight default link racketNumber Number
+highlight default link racketNumberError Error
+highlight default link racketContainedNumberError Error
+
+highlight default link racketQuote SpecialChar
+highlight default link racketUnquote SpecialChar
+
+highlight default link racketDelimiter Delimiter
+highlight default link racketParen Delimiter
+highlight default link racketConstant Constant
+
+highlight default link racketLit Type
+highlight default link racketRe Type
+
+highlight default link racketComment Comment
+highlight default link racketMultilineComment Comment
+highlight default link racketFormComment SpecialChar
+highlight default link racketSharpBang Comment
+highlight default link racketTodo Todo
+highlight default link racketNote SpecialComment
+highlight default link racketError Error
+
+highlight default link racketExtSyntax Type
+highlight default link racketExtFunc PreProc
+
+let b:current_syntax = "racket"
diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim
index e44699faa5..822b1a9ed2 100644
--- a/runtime/syntax/sh.vim
+++ b/runtime/syntax/sh.vim
@@ -2,8 +2,8 @@
" Language: shell (sh) Korn shell (ksh) bash (sh)
" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
" Previous Maintainer: Lennart Schultz <Lennart.Schultz@ecmwf.int>
-" Last Change: Jun 29, 2022
-" Version: 202
+" Last Change: Jul 08, 2022
+" Version: 203
" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
" For options and settings, please use: :help ft-sh-syntax
" This file includes many ideas from Eric Brunet (eric.brunet@ens.fr) and heredoc fixes from Felipe Contreras
@@ -141,7 +141,7 @@ endif
syn cluster shArithParenList contains=shArithmetic,shArithParen,shCaseEsac,shComment,shDeref,shDo,shDerefSimple,shEcho,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shExDoubleQuote,shHereString,shRedir,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen,bashSpecialVariables,bashStatement,shIf,shFor,shFunctionKey,shFunctionOne,shFunctionTwo
syn cluster shArithList contains=@shArithParenList,shParenError
syn cluster shCaseEsacList contains=shCaseStart,shCaseLabel,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial,shCaseRange
-syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSubBQ,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq
+syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSubBQ,shComment,shDblBrace,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq
if exists("b:is_kornshell") || exists("b:is_bash")
syn cluster shCaseList add=shForPP
endif
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..5ec99c7e05 100644
--- a/runtime/syntax/syntax.vim
+++ b/runtime/syntax/syntax.vim
@@ -27,12 +27,13 @@ else
endif
" Set up the connection between FileType and Syntax autocommands.
-" This makes the syntax automatically set when the file type is detected.
+" This makes the syntax automatically set when the file type is detected
+" unless treesitter highlighting is enabled.
+" Avoid an error when 'verbose' is set and <amatch> expansion fails.
augroup syntaxset
- au! FileType * exe "set syntax=" . expand("<amatch>")
+ au! FileType * if !exists('b:ts_highlight') | 0verbose exe "set syntax=" . expand("<amatch>") | endif
augroup END
-
" Execute the syntax autocommands for the each buffer.
" If the filetype wasn't detected yet, do that now.
" Always do the syntaxset autocommands, for buffers where the 'filetype'
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index 2b1c58c449..d5e138dbc3 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -53,7 +53,7 @@ syn case ignore
syn keyword vimGroup contained Comment Constant String Character Number Boolean Float Identifier Function Statement Conditional Repeat Label Operator Keyword Exception PreProc Include Define Macro PreCondit Type StorageClass Structure Typedef Special SpecialChar Tag Delimiter SpecialComment Debug Underlined Ignore Error Todo
" Default highlighting groups {{{2
-syn keyword vimHLGroup contained ColorColumn Cursor CursorColumn CursorIM CursorLine CursorLineFold CursorLineNr CursorLineSign DiffAdd DiffChange DiffDelete DiffText Directory EndOfBuffer ErrorMsg FoldColumn Folded IncSearch LineNr MatchParen Menu ModeMsg MoreMsg NonText Normal Pmenu PmenuSbar PmenuSel PmenuThumb Question QuickFixLine Scrollbar Search SignColumn SpecialKey SpellBad SpellCap SpellLocal SpellRare StatusLine StatusLineNC TabLine TabLineFill TabLineSel Title Tooltip VertSplit Visual WarningMsg WildMenu
+syn keyword vimHLGroup contained ColorColumn Cursor CursorColumn CursorIM CursorLine CursorLineFold CursorLineNr CursorLineSign DiffAdd DiffChange DiffDelete DiffText Directory EndOfBuffer ErrorMsg FoldColumn Folded IncSearch LineNr MatchParen Menu MessageWindow ModeMsg MoreMsg NonText Normal Pmenu PmenuSbar PmenuSel PmenuThumb Question QuickFixLine Scrollbar Search SignColumn SpecialKey SpellBad SpellCap SpellLocal SpellRare StatusLine StatusLineNC TabLine TabLineFill TabLineSel Title Tooltip VertSplit Visual WarningMsg WildMenu
syn match vimHLGroup contained "Conceal"
syn keyword vimOnlyHLGroup contained LineNrAbove LineNrBelow StatusLineTerm Terminal VisualNOS
syn keyword nvimHLGroup contained Substitute TermCursor TermCursorNC
diff --git a/runtime/syntax/zsh.vim b/runtime/syntax/zsh.vim
index bab89b916e..69671c59ca 100644
--- a/runtime/syntax/zsh.vim
+++ b/runtime/syntax/zsh.vim
@@ -2,7 +2,7 @@
" Language: Zsh shell script
" Maintainer: Christian Brabandt <cb@256bit.org>
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2020-11-21
+" Latest Revision: 2022-07-26
" License: Vim (see :h license)
" Repository: https://github.com/chrisbra/vim-zsh
@@ -19,9 +19,9 @@ function! s:ContainedGroup()
" vim-pandoc syntax defines the @langname cluster for embedded syntax languages
" However, if no syntax is defined yet, `syn list @zsh` will return
" "No syntax items defined", so make sure the result is actually a valid syn cluster
- for cluster in ['markdownHighlightzsh', 'zsh']
+ for cluster in ['markdownHighlight_zsh', 'zsh']
try
- " markdown syntax defines embedded clusters as @markdownhighlight<lang>,
+ " markdown syntax defines embedded clusters as @markdownhighlight_<lang>,
" pandoc just uses @<lang>, so check both for both clusters
let a=split(execute('syn list @'. cluster), "\n")
if len(a) == 2 && a[0] =~# '^---' && a[1] =~? cluster
@@ -48,17 +48,28 @@ syn match zshPOSIXQuoted '\\u[0-9a-fA-F]\{1,4}'
syn match zshPOSIXQuoted '\\U[1-9a-fA-F]\{1,8}'
syn region zshString matchgroup=zshStringDelimiter start=+"+ end=+"+
- \ contains=zshQuoted,@zshDerefs,@zshSubst fold
+ \ contains=zshQuoted,@zshDerefs,@zshSubstQuoted fold
syn region zshString matchgroup=zshStringDelimiter start=+'+ end=+'+ fold
syn region zshPOSIXString matchgroup=zshStringDelimiter start=+\$'+
\ skip=+\\[\\']+ end=+'+ contains=zshPOSIXQuoted,zshQuoted
syn match zshJobSpec '%\(\d\+\|?\=\w\+\|[%+-]\)'
+syn match zshNumber '[+-]\=\<\d\+\>'
+syn match zshNumber '[+-]\=\<0x\x\+\>'
+syn match zshNumber '[+-]\=\<0\o\+\>'
+syn match zshNumber '[+-]\=\d\+#[-+]\=\w\+\>'
+syn match zshNumber '[+-]\=\d\+\.\d\+\>'
+
syn keyword zshPrecommand noglob nocorrect exec command builtin - time
syn keyword zshDelimiter do done end
-syn keyword zshConditional if then elif else fi case in esac select
+syn keyword zshConditional if then elif else fi esac select
+
+syn keyword zshCase case nextgroup=zshCaseWord skipwhite
+syn match zshCaseWord /\S\+/ nextgroup=zshCaseIn skipwhite contained transparent
+syn keyword zshCaseIn in nextgroup=zshCasePattern skipwhite skipnl contained
+syn match zshCasePattern /\S[^)]*)/ contained
syn keyword zshRepeat while until repeat
@@ -73,9 +84,13 @@ syn match zshFunction '^\s*\k\+\ze\s*()'
syn match zshOperator '||\|&&\|;\|&!\='
-syn match zshRedir '\d\=\(<\|<>\|<<<\|<&\s*[0-9p-]\=\)'
-syn match zshRedir '\d\=\(>\|>>\|>&\s*[0-9p-]\=\|&>\|>>&\|&>>\)[|!]\='
-syn match zshRedir '|&\='
+ " <<<, <, <>, and variants.
+syn match zshRedir '\d\=\(<<<\|<&\s*[0-9p-]\=\|<>\?\)'
+ " >, >>, and variants.
+syn match zshRedir '\d\=\(>&\s*[0-9p-]\=\|&>>\?\|>>\?&\?\)[|!]\='
+ " | and |&, but only if it's not preceeded or
+ " followed by a | to avoid matching ||.
+syn match zshRedir '|\@1<!|&\=|\@!'
syn region zshHereDoc matchgroup=zshRedir
\ start='<\@<!<<\s*\z([^<]\S*\)'
@@ -125,7 +140,7 @@ syn keyword zshCommands alias autoload bg bindkey break bye cap cd
\ enable eval exec exit export false fc fg
\ functions getcap getln getopts hash history
\ jobs kill let limit log logout popd print
- \ printf pushd pushln pwd r read
+ \ printf prompt pushd pushln pwd r read
\ rehash return sched set setcap shift
\ source stat suspend test times trap true
\ ttyctl type ulimit umask unalias unfunction
@@ -139,10 +154,120 @@ syn case ignore
syn match zshOptStart
\ /\v^\s*%(%(un)?setopt|set\s+[-+]o)/
\ nextgroup=zshOption skipwhite
-syn match zshOption nextgroup=zshOption,zshComment skipwhite contained /\v
- \ <%(no_?)?%(
- \ auto_?cd|auto_?pushd|cdable_?vars|cd_?silent|chase_?dots|chase_?links|posix_?cd|pushd_?ignore_?dups|pushd_?minus|pushd_?silent|pushd_?to_?home|always_?last_?prompt|always_?to_?end|auto_?list|auto_?menu|auto_?name_?dirs|auto_?param_?keys|auto_?param_?slash|auto_?remove_?slash|bash_?auto_?list|complete_?aliases|complete_?in_?word|glob_?complete|hash_?list_?all|list_?ambiguous|list_?beep|list_?packed|list_?rows_?first|list_?types|menu_?complete|rec_?exact|bad_?pattern|bare_?glob_?qual|brace_?ccl|case_?glob|case_?match|case_?paths|csh_?null_?glob|equals|extended_?glob|force_?float|glob|glob_?assign|glob_?dots|glob_?star_?short|glob_?subst|hist_?subst_?pattern|ignore_?braces|ignore_?close_?braces|ksh_?glob|magic_?equal_?subst|mark_?dirs|multibyte|nomatch|null_?glob|numeric_?glob_?sort|rc_?expand_?param|rematch_?pcre|sh_?glob|unset|warn_?create_?global|warn_?nested_?var|warnnestedvar|append_?history|bang_?hist|extended_?history|hist_?allow_?clobber|hist_?beep|hist_?expire_?dups_?first|hist_?fcntl_?lock|hist_?find_?no_?dups|hist_?ignore_?all_?dups|hist_?ignore_?dups|hist_?ignore_?space|hist_?lex_?words|hist_?no_?functions|hist_?no_?store|hist_?reduce_?blanks|hist_?save_?by_?copy|hist_?save_?no_?dups|hist_?verify|inc_?append_?history|inc_?append_?history_?time|share_?history|all_?export|global_?export|global_?rcs|rcs|aliases|clobber|clobber_?empty|correct|correct_?all|dvorak|flow_?control|ignore_?eof|interactive_?comments|hash_?cmds|hash_?dirs|hash_?executables_?only|mail_?warning|path_?dirs|path_?script|print_?eight_?bit|print_?exit_?value|rc_?quotes|rm_?star_?silent|rm_?star_?wait|short_?loops|short_?repeat|sun_?keyboard_?hack|auto_?continue|auto_?resume|bg_?nice|check_?jobs|check_?running_?jobs|hup|long_?list_?jobs|monitor|notify|posix_?jobs|prompt_?bang|prompt_?cr|prompt_?sp|prompt_?percent|prompt_?subst|transient_?rprompt|alias_?func_?def|c_?bases|c_?precedences|debug_?before_?cmd|err_?exit|err_?return|eval_?lineno|exec|function_?argzero|local_?loops|local_?options|local_?patterns|local_?traps|multi_?func_?def|multios|octal_?zeroes|pipe_?fail|source_?trace|typeset_?silent|typeset_?to_?unset|verbose|xtrace|append_?create|bash_?rematch|bsd_?echo|continue_?on_?error|csh_?junkie_?history|csh_?junkie_?loops|csh_?junkie_?quotes|csh_?nullcmd|ksh_?arrays|ksh_?autoload|ksh_?option_?print|ksh_?typeset|ksh_?zero_?subscript|posix_?aliases|posix_?argzero|posix_?builtins|posix_?identifiers|posix_?strings|posix_?traps|sh_?file_?expansion|sh_?nullcmd|sh_?option_?letters|sh_?word_?split|traps_?async|interactive|login|privileged|restricted|shin_?stdin|single_?command|beep|combining_?chars|emacs|overstrike|single_?line_?zle|vi|zle|brace_?expand|dot_?glob|hash_?all|hist_?append|hist_?expand|log|mail_?warn|one_?cmd|physical|prompt_?vars|stdin|track_?all|no_?match
- \)>/
+syn keyword zshOption nextgroup=zshOption,zshComment skipwhite contained
+ \ auto_cd no_auto_cd autocd noautocd auto_pushd no_auto_pushd autopushd noautopushd cdable_vars
+ \ no_cdable_vars cdablevars nocdablevars cd_silent no_cd_silent cdsilent nocdsilent chase_dots
+ \ no_chase_dots chasedots nochasedots chase_links no_chase_links chaselinks nochaselinks posix_cd
+ \ posixcd no_posix_cd noposixcd pushd_ignore_dups no_pushd_ignore_dups pushdignoredups
+ \ nopushdignoredups pushd_minus no_pushd_minus pushdminus nopushdminus pushd_silent no_pushd_silent
+ \ pushdsilent nopushdsilent pushd_to_home no_pushd_to_home pushdtohome nopushdtohome
+ \ always_last_prompt no_always_last_prompt alwayslastprompt noalwayslastprompt always_to_end
+ \ no_always_to_end alwaystoend noalwaystoend auto_list no_auto_list autolist noautolist auto_menu
+ \ no_auto_menu automenu noautomenu auto_name_dirs no_auto_name_dirs autonamedirs noautonamedirs
+ \ auto_param_keys no_auto_param_keys autoparamkeys noautoparamkeys auto_param_slash
+ \ no_auto_param_slash autoparamslash noautoparamslash auto_remove_slash no_auto_remove_slash
+ \ autoremoveslash noautoremoveslash bash_auto_list no_bash_auto_list bashautolist nobashautolist
+ \ complete_aliases no_complete_aliases completealiases nocompletealiases complete_in_word
+ \ no_complete_in_word completeinword nocompleteinword glob_complete no_glob_complete globcomplete
+ \ noglobcomplete hash_list_all no_hash_list_all hashlistall nohashlistall list_ambiguous
+ \ no_list_ambiguous listambiguous nolistambiguous list_beep no_list_beep listbeep nolistbeep
+ \ list_packed no_list_packed listpacked nolistpacked list_rows_first no_list_rows_first listrowsfirst
+ \ nolistrowsfirst list_types no_list_types listtypes nolisttypes menu_complete no_menu_complete
+ \ menucomplete nomenucomplete rec_exact no_rec_exact recexact norecexact bad_pattern no_bad_pattern
+ \ badpattern nobadpattern bare_glob_qual no_bare_glob_qual bareglobqual nobareglobqual brace_ccl
+ \ no_brace_ccl braceccl nobraceccl case_glob no_case_glob caseglob nocaseglob case_match
+ \ no_case_match casematch nocasematch case_paths no_case_paths casepaths nocasepaths csh_null_glob
+ \ no_csh_null_glob cshnullglob nocshnullglob equals no_equals noequals extended_glob no_extended_glob
+ \ extendedglob noextendedglob force_float no_force_float forcefloat noforcefloat glob no_glob noglob
+ \ glob_assign no_glob_assign globassign noglobassign glob_dots no_glob_dots globdots noglobdots
+ \ glob_star_short no_glob_star_short globstarshort noglobstarshort glob_subst no_glob_subst globsubst
+ \ noglobsubst hist_subst_pattern no_hist_subst_pattern histsubstpattern nohistsubstpattern
+ \ ignore_braces no_ignore_braces ignorebraces noignorebraces ignore_close_braces
+ \ no_ignore_close_braces ignoreclosebraces noignoreclosebraces ksh_glob no_ksh_glob kshglob nokshglob
+ \ magic_equal_subst no_magic_equal_subst magicequalsubst nomagicequalsubst mark_dirs no_mark_dirs
+ \ markdirs nomarkdirs multibyte no_multibyte nomultibyte nomatch no_nomatch nonomatch null_glob
+ \ no_null_glob nullglob nonullglob numeric_glob_sort no_numeric_glob_sort numericglobsort
+ \ nonumericglobsort rc_expand_param no_rc_expand_param rcexpandparam norcexpandparam rematch_pcre
+ \ no_rematch_pcre rematchpcre norematchpcre sh_glob no_sh_glob shglob noshglob unset no_unset nounset
+ \ warn_create_global no_warn_create_global warncreateglobal nowarncreateglobal warn_nested_var
+ \ no_warn_nested_var warnnestedvar no_warnnestedvar append_history no_append_history appendhistory
+ \ noappendhistory bang_hist no_bang_hist banghist nobanghist extended_history no_extended_history
+ \ extendedhistory noextendedhistory hist_allow_clobber no_hist_allow_clobber histallowclobber
+ \ nohistallowclobber hist_beep no_hist_beep histbeep nohistbeep hist_expire_dups_first
+ \ no_hist_expire_dups_first histexpiredupsfirst nohistexpiredupsfirst hist_fcntl_lock
+ \ no_hist_fcntl_lock histfcntllock nohistfcntllock hist_find_no_dups no_hist_find_no_dups
+ \ histfindnodups nohistfindnodups hist_ignore_all_dups no_hist_ignore_all_dups histignorealldups
+ \ nohistignorealldups hist_ignore_dups no_hist_ignore_dups histignoredups nohistignoredups
+ \ hist_ignore_space no_hist_ignore_space histignorespace nohistignorespace hist_lex_words
+ \ no_hist_lex_words histlexwords nohistlexwords hist_no_functions no_hist_no_functions
+ \ histnofunctions nohistnofunctions hist_no_store no_hist_no_store histnostore nohistnostore
+ \ hist_reduce_blanks no_hist_reduce_blanks histreduceblanks nohistreduceblanks hist_save_by_copy
+ \ no_hist_save_by_copy histsavebycopy nohistsavebycopy hist_save_no_dups no_hist_save_no_dups
+ \ histsavenodups nohistsavenodups hist_verify no_hist_verify histverify nohistverify
+ \ inc_append_history no_inc_append_history incappendhistory noincappendhistory
+ \ inc_append_history_time no_inc_append_history_time incappendhistorytime noincappendhistorytime
+ \ share_history no_share_history sharehistory nosharehistory all_export no_all_export allexport
+ \ noallexport global_export no_global_export globalexport noglobalexport global_rcs no_global_rcs
+ \ globalrcs noglobalrcs rcs no_rcs norcs aliases no_aliases noaliases clobber no_clobber noclobber
+ \ clobber_empty no_clobber_empty clobberempty noclobberempty correct no_correct nocorrect correct_all
+ \ no_correct_all correctall nocorrectall dvorak no_dvorak nodvorak flow_control no_flow_control
+ \ flowcontrol noflowcontrol ignore_eof no_ignore_eof ignoreeof noignoreeof interactive_comments
+ \ no_interactive_comments interactivecomments nointeractivecomments hash_cmds no_hash_cmds hashcmds
+ \ nohashcmds hash_dirs no_hash_dirs hashdirs nohashdirs hash_executables_only
+ \ no_hash_executables_only hashexecutablesonly nohashexecutablesonly mail_warning no_mail_warning
+ \ mailwarning nomailwarning path_dirs no_path_dirs pathdirs nopathdirs path_script no_path_script
+ \ pathscript nopathscript print_eight_bit no_print_eight_bit printeightbit noprinteightbit
+ \ print_exit_value no_print_exit_value printexitvalue noprintexitvalue rc_quotes no_rc_quotes
+ \ rcquotes norcquotes rm_star_silent no_rm_star_silent rmstarsilent normstarsilent rm_star_wait
+ \ no_rm_star_wait rmstarwait normstarwait short_loops no_short_loops shortloops noshortloops
+ \ short_repeat no_short_repeat shortrepeat noshortrepeat sun_keyboard_hack no_sun_keyboard_hack
+ \ sunkeyboardhack nosunkeyboardhack auto_continue no_auto_continue autocontinue noautocontinue
+ \ auto_resume no_auto_resume autoresume noautoresume bg_nice no_bg_nice bgnice nobgnice check_jobs
+ \ no_check_jobs checkjobs nocheckjobs check_running_jobs no_check_running_jobs checkrunningjobs
+ \ nocheckrunningjobs hup no_hup nohup long_list_jobs no_long_list_jobs longlistjobs nolonglistjobs
+ \ monitor no_monitor nomonitor notify no_notify nonotify posix_jobs posixjobs no_posix_jobs
+ \ noposixjobs prompt_bang no_prompt_bang promptbang nopromptbang prompt_cr no_prompt_cr promptcr
+ \ nopromptcr prompt_sp no_prompt_sp promptsp nopromptsp prompt_percent no_prompt_percent
+ \ promptpercent nopromptpercent prompt_subst no_prompt_subst promptsubst nopromptsubst
+ \ transient_rprompt no_transient_rprompt transientrprompt notransientrprompt alias_func_def
+ \ no_alias_func_def aliasfuncdef noaliasfuncdef c_bases no_c_bases cbases nocbases c_precedences
+ \ no_c_precedences cprecedences nocprecedences debug_before_cmd no_debug_before_cmd debugbeforecmd
+ \ nodebugbeforecmd err_exit no_err_exit errexit noerrexit err_return no_err_return errreturn
+ \ noerrreturn eval_lineno no_eval_lineno evallineno noevallineno exec no_exec noexec function_argzero
+ \ no_function_argzero functionargzero nofunctionargzero local_loops no_local_loops localloops
+ \ nolocalloops local_options no_local_options localoptions nolocaloptions local_patterns
+ \ no_local_patterns localpatterns nolocalpatterns local_traps no_local_traps localtraps nolocaltraps
+ \ multi_func_def no_multi_func_def multifuncdef nomultifuncdef multios no_multios nomultios
+ \ octal_zeroes no_octal_zeroes octalzeroes nooctalzeroes pipe_fail no_pipe_fail pipefail nopipefail
+ \ source_trace no_source_trace sourcetrace nosourcetrace typeset_silent no_typeset_silent
+ \ typesetsilent notypesetsilent typeset_to_unset no_typeset_to_unset typesettounset notypesettounset
+ \ verbose no_verbose noverbose xtrace no_xtrace noxtrace append_create no_append_create appendcreate
+ \ noappendcreate bash_rematch no_bash_rematch bashrematch nobashrematch bsd_echo no_bsd_echo bsdecho
+ \ nobsdecho continue_on_error no_continue_on_error continueonerror nocontinueonerror
+ \ csh_junkie_history no_csh_junkie_history cshjunkiehistory nocshjunkiehistory csh_junkie_loops
+ \ no_csh_junkie_loops cshjunkieloops nocshjunkieloops csh_junkie_quotes no_csh_junkie_quotes
+ \ cshjunkiequotes nocshjunkiequotes csh_nullcmd no_csh_nullcmd cshnullcmd nocshnullcmd ksh_arrays
+ \ no_ksh_arrays ksharrays noksharrays ksh_autoload no_ksh_autoload kshautoload nokshautoload
+ \ ksh_option_print no_ksh_option_print kshoptionprint nokshoptionprint ksh_typeset no_ksh_typeset
+ \ kshtypeset nokshtypeset ksh_zero_subscript no_ksh_zero_subscript kshzerosubscript
+ \ nokshzerosubscript posix_aliases no_posix_aliases posixaliases noposixaliases posix_argzero
+ \ no_posix_argzero posixargzero noposixargzero posix_builtins no_posix_builtins posixbuiltins
+ \ noposixbuiltins posix_identifiers no_posix_identifiers posixidentifiers noposixidentifiers
+ \ posix_strings no_posix_strings posixstrings noposixstrings posix_traps no_posix_traps posixtraps
+ \ noposixtraps sh_file_expansion no_sh_file_expansion shfileexpansion noshfileexpansion sh_nullcmd
+ \ no_sh_nullcmd shnullcmd noshnullcmd sh_option_letters no_sh_option_letters shoptionletters
+ \ noshoptionletters sh_word_split no_sh_word_split shwordsplit noshwordsplit traps_async
+ \ no_traps_async trapsasync notrapsasync interactive no_interactive nointeractive login no_login
+ \ nologin privileged no_privileged noprivileged restricted no_restricted norestricted shin_stdin
+ \ no_shin_stdin shinstdin noshinstdin single_command no_single_command singlecommand nosinglecommand
+ \ beep no_beep nobeep combining_chars no_combining_chars combiningchars nocombiningchars emacs
+ \ no_emacs noemacs overstrike no_overstrike nooverstrike single_line_zle no_single_line_zle
+ \ singlelinezle nosinglelinezle vi no_vi novi zle no_zle nozle brace_expand no_brace_expand
+ \ braceexpand nobraceexpand dot_glob no_dot_glob dotglob nodotglob hash_all no_hash_all hashall
+ \ nohashall hist_append no_hist_append histappend nohistappend hist_expand no_hist_expand histexpand
+ \ nohistexpand log no_log nolog mail_warn no_mail_warn mailwarn nomailwarn one_cmd no_one_cmd onecmd
+ \ noonecmd physical no_physical nophysical prompt_vars no_prompt_vars promptvars nopromptvars stdin
+ \ no_stdin nostdin track_all no_track_all trackall notrackall
syn case match
syn keyword zshTypes float integer local typeset declare private readonly
@@ -150,15 +275,12 @@ syn keyword zshTypes float integer local typeset declare private read
" XXX: this may be too much
" syn match zshSwitches '\s\zs--\=[a-zA-Z0-9-]\+'
-syn match zshNumber '[+-]\=\<\d\+\>'
-syn match zshNumber '[+-]\=\<0x\x\+\>'
-syn match zshNumber '[+-]\=\<0\o\+\>'
-syn match zshNumber '[+-]\=\d\+#[-+]\=\w\+\>'
-syn match zshNumber '[+-]\=\d\+\.\d\+\>'
-
" TODO: $[...] is the same as $((...)), so add that as well.
syn cluster zshSubst contains=zshSubst,zshOldSubst,zshMathSubst
+syn cluster zshSubstQuoted contains=zshSubstQuoted,zshOldSubst,zshMathSubst
exe 'syn region zshSubst matchgroup=zshSubstDelim transparent start=/\$(/ skip=/\\)/ end=/)/ contains='.s:contained. ' fold'
+exe 'syn region zshSubstQuoted matchgroup=zshSubstDelim transparent start=/\$(/ skip=/\\)/ end=/)/ contains='.s:contained. ' fold'
+syn region zshSubstQuoted matchgroup=zshSubstDelim start='\${' skip='\\}' end='}' contains=@zshSubst,zshBrackets,zshQuoted fold
syn region zshParentheses transparent start='(' skip='\\)' end=')' fold
syn region zshGlob start='(#' end=')'
syn region zshMathSubst matchgroup=zshSubstDelim transparent
@@ -201,6 +323,8 @@ hi def link zshJobSpec Special
hi def link zshPrecommand Special
hi def link zshDelimiter Keyword
hi def link zshConditional Conditional
+hi def link zshCase zshConditional
+hi def link zshCaseIn zshCase
hi def link zshException Exception
hi def link zshRepeat Repeat
hi def link zshKeyword Keyword
@@ -223,6 +347,7 @@ hi def link zshTypes Type
hi def link zshSwitches Special
hi def link zshNumber Number
hi def link zshSubst PreProc
+hi def link zshSubstQuoted zshSubst
hi def link zshMathSubst zshSubst
hi def link zshOldSubst zshSubst
hi def link zshSubstDelim zshSubst
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/clint.py b/src/clint.py
index 28f6031a57..0556f53372 100755
--- a/src/clint.py
+++ b/src/clint.py
@@ -1941,13 +1941,6 @@ def CheckExpressionAlignment(filename, clean_lines, linenum, error, startpos=0):
error(filename, linenum, 'whitespace/indent', 2,
'End of the inner expression should have '
'the same indent as start')
- else:
- if (pos != depth_line_starts[depth][0] + 4
- and not (depth_line_starts[depth][1] == '{'
- and pos == depth_line_starts[depth][0] + 2)):
- if depth not in ignore_error_levels:
- error(filename, linenum, 'whitespace/indent', 2,
- 'Inner expression indentation should be 4')
else:
if (pos != level_starts[depth][0] + 1
+ (level_starts[depth][2] == '{')):
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 635833748d..a1b57f927e 100755
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -443,11 +443,6 @@ endif()
set(NVIM_EXEC_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES} ${LUA_PREFERRED_LIBRARIES})
-# Add IPO flags (for LTO), or error if CMake does not know the flags. #8654
-if(POLICY CMP0069)
- cmake_policy(SET CMP0069 NEW)
-endif()
-
add_executable(nvim ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS}
${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS})
@@ -461,7 +456,7 @@ set_property(TARGET nvim APPEND PROPERTY
INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS})
set_property(TARGET nvim PROPERTY ENABLE_EXPORTS TRUE)
-if(ENABLE_LTO AND (POLICY CMP0069))
+if(ENABLE_LTO)
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
if(IPO_SUPPORTED AND (NOT CMAKE_BUILD_TYPE MATCHES Debug))
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..6f8cad3e33 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -570,7 +570,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
char *str_at_end = NULL;
// Another call to ml_get_buf() may free the line, so make a copy.
- str_at_start = xstrdup((char *)ml_get_buf(buf, (linenr_T)start_row, false));
+ str_at_start = xstrdup(ml_get_buf(buf, (linenr_T)start_row, false));
size_t len_at_start = strlen(str_at_start);
if (start_col < 0 || (size_t)start_col > len_at_start) {
api_set_error(err, kErrorTypeValidation, "start_col out of bounds");
@@ -578,7 +578,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
}
// Another call to ml_get_buf() may free the line, so make a copy.
- str_at_end = xstrdup((char *)ml_get_buf(buf, (linenr_T)end_row, false));
+ str_at_end = xstrdup(ml_get_buf(buf, (linenr_T)end_row, false));
size_t len_at_end = strlen(str_at_end);
if (end_col < 0 || (size_t)end_col > len_at_end) {
api_set_error(err, kErrorTypeValidation, "end_col out of bounds");
@@ -608,7 +608,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
for (int64_t i = 1; i < end_row - start_row; i++) {
int64_t lnum = start_row + i;
- const char *bufline = (char *)ml_get_buf(buf, (linenr_T)lnum, false);
+ const char *bufline = ml_get_buf(buf, (linenr_T)lnum, false);
old_byte += (bcount_t)(strlen(bufline)) + 1;
}
old_byte += (bcount_t)end_col + 1;
@@ -945,7 +945,7 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err)
/// @param[out] err Error details, if any
/// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key holds the associated buffer handle.
-ArrayOf(Dictionary) nvim_buf_get_keymap(uint64_t channel_id, Buffer buffer, String mode, Error *err)
+ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err)
FUNC_API_SINCE(3)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -954,7 +954,7 @@ ArrayOf(Dictionary) nvim_buf_get_keymap(uint64_t channel_id, Buffer buffer, Stri
return (Array)ARRAY_DICT_INIT;
}
- return keymap_array(mode, buf, channel_id == LUA_INTERNAL_CALL);
+ return keymap_array(mode, buf);
}
/// Sets a buffer-local |mapping| for the given mode.
@@ -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/command.c b/src/nvim/api/command.c
index 1323fc347b..b3518f1b0f 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -62,13 +62,14 @@
/// - browse: (boolean) |:browse|.
/// - confirm: (boolean) |:confirm|.
/// - hide: (boolean) |:hide|.
+/// - horizontal: (boolean) |:horizontal|.
/// - keepalt: (boolean) |:keepalt|.
/// - keepjumps: (boolean) |:keepjumps|.
/// - keepmarks: (boolean) |:keepmarks|.
/// - keeppatterns: (boolean) |:keeppatterns|.
/// - lockmarks: (boolean) |:lockmarks|.
/// - noswapfile: (boolean) |:noswapfile|.
-/// - tab: (integer) |:tab|.
+/// - tab: (integer) |:tab|. -1 when omitted.
/// - verbose: (integer) |:verbose|. -1 when omitted.
/// - vertical: (boolean) |:vertical|.
/// - split: (string) Split modifier string, is an empty string when there's no split
@@ -238,7 +239,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
PUT(mods, "unsilent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_UNSILENT));
PUT(mods, "sandbox", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SANDBOX));
PUT(mods, "noautocmd", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOAUTOCMD));
- PUT(mods, "tab", INTEGER_OBJ(cmdinfo.cmdmod.cmod_tab));
+ PUT(mods, "tab", INTEGER_OBJ(cmdinfo.cmdmod.cmod_tab - 1));
PUT(mods, "verbose", INTEGER_OBJ(cmdinfo.cmdmod.cmod_verbose - 1));
PUT(mods, "browse", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_BROWSE));
PUT(mods, "confirm", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_CONFIRM));
@@ -250,6 +251,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
PUT(mods, "lockmarks", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_LOCKMARKS));
PUT(mods, "noswapfile", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOSWAPFILE));
PUT(mods, "vertical", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_VERT));
+ PUT(mods, "horizontal", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_HOR));
const char *split;
if (cmdinfo.cmdmod.cmod_split & WSP_BOT) {
@@ -557,15 +559,17 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
}
if (HAS_KEY(mods.tab)) {
- if (mods.tab.type != kObjectTypeInteger || mods.tab.data.integer < 0) {
- VALIDATION_ERROR("'mods.tab' must be a non-negative Integer");
+ if (mods.tab.type != kObjectTypeInteger) {
+ VALIDATION_ERROR("'mods.tab' must be an Integer");
+ } else if ((int)mods.tab.data.integer >= 0) {
+ // Silently ignore negative integers to allow mods.tab to be set to -1.
+ cmdinfo.cmdmod.cmod_tab = (int)mods.tab.data.integer + 1;
}
- cmdinfo.cmdmod.cmod_tab = (int)mods.tab.data.integer + 1;
}
if (HAS_KEY(mods.verbose)) {
if (mods.verbose.type != kObjectTypeInteger) {
- VALIDATION_ERROR("'mods.verbose' must be a Integer");
+ VALIDATION_ERROR("'mods.verbose' must be an Integer");
} else if ((int)mods.verbose.data.integer >= 0) {
// Silently ignore negative integers to allow mods.verbose to be set to -1.
cmdinfo.cmdmod.cmod_verbose = (int)mods.verbose.data.integer + 1;
@@ -576,6 +580,10 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
OBJ_TO_BOOL(vertical, mods.vertical, false, "'mods.vertical'");
cmdinfo.cmdmod.cmod_split |= (vertical ? WSP_VERT : 0);
+ bool horizontal;
+ OBJ_TO_BOOL(horizontal, mods.horizontal, false, "'mods.horizontal'");
+ cmdinfo.cmdmod.cmod_split |= (horizontal ? WSP_HOR : 0);
+
if (HAS_KEY(mods.split)) {
if (mods.split.type != kObjectTypeString) {
VALIDATION_ERROR("'mods.split' must be a String");
@@ -583,15 +591,15 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
if (*mods.split.data.string.data == NUL) {
// Empty string, do nothing.
- } else if (STRCMP(mods.split.data.string.data, "aboveleft") == 0
- || STRCMP(mods.split.data.string.data, "leftabove") == 0) {
+ } else if (strcmp(mods.split.data.string.data, "aboveleft") == 0
+ || strcmp(mods.split.data.string.data, "leftabove") == 0) {
cmdinfo.cmdmod.cmod_split |= WSP_ABOVE;
- } else if (STRCMP(mods.split.data.string.data, "belowright") == 0
- || STRCMP(mods.split.data.string.data, "rightbelow") == 0) {
+ } else if (strcmp(mods.split.data.string.data, "belowright") == 0
+ || strcmp(mods.split.data.string.data, "rightbelow") == 0) {
cmdinfo.cmdmod.cmod_split |= WSP_BELOW;
- } else if (STRCMP(mods.split.data.string.data, "topleft") == 0) {
+ } else if (strcmp(mods.split.data.string.data, "topleft") == 0) {
cmdinfo.cmdmod.cmod_split |= WSP_TOP;
- } else if (STRCMP(mods.split.data.string.data, "botright") == 0) {
+ } else if (strcmp(mods.split.data.string.data, "botright") == 0) {
cmdinfo.cmdmod.cmod_split |= WSP_BOT;
} else {
VALIDATION_ERROR("Invalid value for 'mods.split'");
@@ -753,6 +761,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
} while (0)
CMDLINE_APPEND_IF(cmdinfo->cmdmod.cmod_split & WSP_VERT, "vertical ");
+ CMDLINE_APPEND_IF(cmdinfo->cmdmod.cmod_split & WSP_HOR, "horizontal ");
CMDLINE_APPEND_IF(cmdinfo->cmdmod.cmod_flags & CMOD_SANDBOX, "sandbox ");
CMDLINE_APPEND_IF(cmdinfo->cmdmod.cmod_flags & CMOD_NOAUTOCMD, "noautocmd ");
CMDLINE_APPEND_IF(cmdinfo->cmdmod.cmod_flags & CMOD_BROWSE, "browse ");
@@ -929,7 +938,7 @@ void nvim_buf_del_user_command(Buffer buffer, String name, Error *err)
for (int i = 0; i < gap->ga_len; i++) {
ucmd_T *cmd = USER_CMD_GA(gap, i);
- if (!STRCMP(name.data, cmd->uc_name)) {
+ if (!strcmp(name.data, cmd->uc_name)) {
free_ucmd(cmd);
gap->ga_len -= 1;
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 933aa85530..ae051d8cab 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;
@@ -87,7 +87,7 @@ const char *describe_ns(NS ns_id)
}
// Is the Namespace in use?
-static bool ns_initialized(uint32_t ns)
+bool ns_initialized(uint32_t ns)
{
if (ns < 1) {
return false;
@@ -473,6 +473,8 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// When a character is supplied it is used as |:syn-cchar|.
/// "hl_group" is used as highlight for the cchar if provided,
/// otherwise it defaults to |hl-Conceal|.
+/// - spell: boolean indicating that spell checking should be
+/// performed within this extmark
/// - ui_watched: boolean that indicates the mark should be drawn
/// by a UI. When set, the UI will receive win_extmark events.
/// Note: the mark is positioned by virt_text attributes. Can be
@@ -719,6 +721,11 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
bool ephemeral = false;
OPTION_TO_BOOL(ephemeral, ephemeral, false);
+ OPTION_TO_BOOL(decor.spell, spell, false);
+ if (decor.spell) {
+ has_decor = true;
+ }
+
OPTION_TO_BOOL(decor.ui_watched, ui_watched, false);
if (decor.ui_watched) {
has_decor = true;
@@ -972,20 +979,21 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
/// for the moment.
///
/// @param ns_id Namespace id from |nvim_create_namespace()|
-/// @param opts Callbacks invoked during redraw:
+/// @param opts Table of callbacks:
/// - on_start: called first on each screen redraw
/// ["start", tick]
-/// - on_buf: called for each buffer being redrawn (before window
-/// callbacks)
+/// - on_buf: called for each buffer being redrawn (before
+/// window callbacks)
/// ["buf", bufnr, tick]
-/// - on_win: called when starting to redraw a specific window.
+/// - on_win: called when starting to redraw a
+/// specific window.
/// ["win", winid, bufnr, topline, botline_guess]
-/// - on_line: called for each buffer line being redrawn. (The
-/// interaction with fold lines is subject to change)
+/// - on_line: called for each buffer line being redrawn.
+/// (The interaction with fold lines is subject to change)
/// ["win", winid, bufnr, row]
/// - on_end: called at the end of a redraw cycle
/// ["end", tick]
-void nvim_set_decoration_provider(Integer ns_id, DictionaryOf(LuaRef) opts, Error *err)
+void nvim_set_decoration_provider(Integer ns_id, Dict(set_decoration_provider) *opts, Error *err)
FUNC_API_SINCE(7) FUNC_API_LUA_ONLY
{
DecorProvider *p = get_decor_provider((NS)ns_id, true);
@@ -993,41 +1001,36 @@ 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;
+ Object *source;
LuaRef *dest;
} cbs[] = {
- { "on_start", &p->redraw_start },
- { "on_buf", &p->redraw_buf },
- { "on_win", &p->redraw_win },
- { "on_line", &p->redraw_line },
- { "on_end", &p->redraw_end },
- { "_on_hl_def", &p->hl_def },
- { NULL, NULL },
+ { "on_start", &opts->on_start, &p->redraw_start },
+ { "on_buf", &opts->on_buf, &p->redraw_buf },
+ { "on_win", &opts->on_win, &p->redraw_win },
+ { "on_line", &opts->on_line, &p->redraw_line },
+ { "on_end", &opts->on_end, &p->redraw_end },
+ { "_on_hl_def", &opts->_on_hl_def, &p->hl_def },
+ { "_on_spell_nav", &opts->_on_spell_nav, &p->spell_nav },
+ { NULL, NULL, NULL },
};
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- size_t j;
- for (j = 0; cbs[j].name && cbs[j].dest; j++) {
- if (strequal(cbs[j].name, k.data)) {
- if (v->type != kObjectTypeLuaRef) {
- api_set_error(err, kErrorTypeValidation,
- "%s is not a function", cbs[j].name);
- goto error;
- }
- *(cbs[j].dest) = v->data.luaref;
- v->data.luaref = LUA_NOREF;
- break;
- }
+ for (size_t i = 0; cbs[i].source && cbs[i].dest && cbs[i].name; i++) {
+ Object *v = cbs[i].source;
+ if (v->type == kObjectTypeNil) {
+ continue;
}
- if (!cbs[j].name) {
- api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
+
+ if (v->type != kObjectTypeLuaRef) {
+ api_set_error(err, kErrorTypeValidation,
+ "%s is not a function", cbs[i].name);
goto error;
}
+ *(cbs[i].dest) = v->data.luaref;
+ v->data.luaref = LUA_NOREF;
}
p->active = true;
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index 6fad52ba75..d9d9c7ee1d 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -2,6 +2,15 @@ return {
context = {
"types";
};
+ set_decoration_provider = {
+ "on_start";
+ "on_buf";
+ "on_win";
+ "on_line";
+ "on_end";
+ "_on_hl_def";
+ "_on_spell_nav";
+ };
set_extmark = {
"id";
"end_line";
@@ -28,6 +37,7 @@ return {
"line_hl_group";
"cursorline_hl_group";
"conceal";
+ "spell";
"ui_watched";
};
keymap = {
@@ -73,6 +83,8 @@ return {
"border";
"style";
"noautocmd";
+ "title";
+ "title_position";
};
runtime = {
"is_lua";
@@ -188,6 +200,7 @@ return {
"browse";
"confirm";
"hide";
+ "horizontal";
"keepalt";
"keepjumps";
"keepmarks";
diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c
index 8724ef4432..b6b3c83f3c 100644
--- a/src/nvim/api/private/converter.c
+++ b/src/nvim/api/private/converter.c
@@ -65,8 +65,8 @@ typedef struct {
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
do { \
ufunc_T *fp = find_func(fun); \
- if (fp != NULL && fp->uf_cb == nlua_CFunction_func_call) { \
- LuaRef ref = api_new_luaref(((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref); \
+ if (fp != NULL && (fp->uf_flags & FC_LUAREF)) { \
+ LuaRef ref = api_new_luaref(fp->uf_luaref); \
kvi_push(edata->stack, LUAREF_OBJ(ref)); \
} else { \
TYPVAL_ENCODE_CONV_NIL(tv); \
@@ -351,10 +351,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
}
case kObjectTypeLuaRef: {
- LuaCFunctionState *state = xmalloc(sizeof(LuaCFunctionState));
- state->lua_callable.func_ref = api_new_luaref(obj.data.luaref);
- char *name =
- (char *)register_cfunc(&nlua_CFunction_func_call, &nlua_CFunction_func_free, state);
+ char *name = (char *)register_luafunc(api_new_luaref(obj.data.luaref));
tv->v_type = VAR_FUNC;
tv->vval.v_string = xstrdup(name);
break;
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..22d2ffbaf1 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();
}
@@ -462,7 +466,7 @@ bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Arr
return false;
}
- const char *bufstr = (char *)ml_get_buf(buf, (linenr_T)lnum, false);
+ const char *bufstr = ml_get_buf(buf, (linenr_T)lnum, false);
Object str = STRING_OBJ(cstr_to_string(bufstr));
if (replace_nl) {
@@ -495,7 +499,7 @@ String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col
return rv;
}
- const char *bufstr = (char *)ml_get_buf(buf, (linenr_T)lnum, false);
+ const char *bufstr = ml_get_buf(buf, (linenr_T)lnum, false);
size_t line_length = strlen(bufstr);
start_col = start_col < 0 ? (int64_t)line_length + start_col + 1 : start_col;
@@ -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..27fb4b8e16 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -223,6 +223,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
ui->msg_set_pos = remote_ui_msg_set_pos;
ui->event = remote_ui_event;
ui->inspect = remote_ui_inspect;
+ ui->win_viewport = remote_ui_win_viewport;
CLEAR_FIELD(ui->ui_ext);
@@ -748,10 +749,12 @@ static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAt
UIData *data = ui->data;
Array args = data->call_buf;
ADD_C(args, INTEGER_OBJ(id));
- MAXSIZE_TEMP_DICT(rgb, 16);
- MAXSIZE_TEMP_DICT(cterm, 16);
- ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(&rgb, rgb_attrs, true)));
- ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(&cterm, cterm_attrs, false)));
+ MAXSIZE_TEMP_DICT(rgb, HLATTRS_DICT_SIZE);
+ MAXSIZE_TEMP_DICT(cterm, HLATTRS_DICT_SIZE);
+ hlattrs2dict(&rgb, rgb_attrs, true);
+ hlattrs2dict(&cterm, rgb_attrs, false);
+ ADD_C(args, DICTIONARY_OBJ(rgb));
+ ADD_C(args, DICTIONARY_OBJ(cterm));
if (ui->ui_ext[kUIHlState]) {
ADD_C(args, ARRAY_OBJ(info));
@@ -771,8 +774,9 @@ static void remote_ui_highlight_set(UI *ui, int id)
return;
}
data->hl_id = id;
- MAXSIZE_TEMP_DICT(dict, 16);
- ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(&dict, syn_attr2entry(id), ui->rgb)));
+ MAXSIZE_TEMP_DICT(dict, HLATTRS_DICT_SIZE);
+ hlattrs2dict(&dict, syn_attr2entry(id), ui->rgb);
+ ADD_C(args, DICTIONARY_OBJ(dict));
push_call(ui, "highlight_set", args);
}
@@ -841,7 +845,7 @@ static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startc
for (size_t i = 0; i < ncells; i++) {
repeat++;
if (i == ncells - 1 || attrs[i] != attrs[i + 1]
- || STRCMP(chunk[i], chunk[i + 1])) {
+ || strcmp(chunk[i], chunk[i + 1])) {
if (UI_BUF_SIZE - BUF_POS(data) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5)) {
// close to overflowing the redraw buffer. finish this event,
// flush, and start a new "grid_line" event at the current position.
@@ -952,65 +956,63 @@ static void remote_ui_flush(UI *ui)
}
}
-static Array translate_contents(UI *ui, Array contents)
+static Array translate_contents(UI *ui, Array contents, Arena *arena)
{
- Array new_contents = ARRAY_DICT_INIT;
+ Array new_contents = arena_array(arena, contents.size);
for (size_t i = 0; i < contents.size; i++) {
Array item = contents.items[i].data.array;
- Array new_item = ARRAY_DICT_INIT;
+ Array new_item = arena_array(arena, 2);
int attr = (int)item.items[0].data.integer;
if (attr) {
- Dictionary rgb_attrs = hlattrs2dict(NULL, syn_attr2entry(attr), ui->rgb);
+ Dictionary rgb_attrs = arena_dict(arena, HLATTRS_DICT_SIZE);
+ hlattrs2dict(&rgb_attrs, syn_attr2entry(attr), ui->rgb);
ADD(new_item, DICTIONARY_OBJ(rgb_attrs));
} else {
ADD(new_item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
}
- ADD(new_item, copy_object(item.items[1]));
+ ADD(new_item, item.items[1]);
ADD(new_contents, ARRAY_OBJ(new_item));
}
return new_contents;
}
-static Array translate_firstarg(UI *ui, Array args)
+static Array translate_firstarg(UI *ui, Array args, Arena *arena)
{
- Array new_args = ARRAY_DICT_INIT;
+ Array new_args = arena_array(arena, args.size);
Array contents = args.items[0].data.array;
- ADD(new_args, ARRAY_OBJ(translate_contents(ui, contents)));
+ ADD_C(new_args, ARRAY_OBJ(translate_contents(ui, contents, arena)));
for (size_t i = 1; i < args.size; i++) {
- ADD(new_args, copy_object(args.items[i]));
+ ADD(new_args, args.items[i]);
}
return new_args;
}
static void remote_ui_event(UI *ui, char *name, Array args)
{
+ Arena arena = ARENA_EMPTY;
UIData *data = ui->data;
if (!ui->ui_ext[kUILinegrid]) {
// the representation of highlights in cmdline changed, translate back
// never consumes args
if (strequal(name, "cmdline_show")) {
- Array new_args = translate_firstarg(ui, args);
+ Array new_args = translate_firstarg(ui, args, &arena);
push_call(ui, name, new_args);
- api_free_array(new_args);
- return;
+ goto free_ret;
} else if (strequal(name, "cmdline_block_show")) {
Array new_args = data->call_buf;
Array block = args.items[0].data.array;
- Array new_block = ARRAY_DICT_INIT;
+ Array new_block = arena_array(&arena, block.size);
for (size_t i = 0; i < block.size; i++) {
- ADD(new_block,
- ARRAY_OBJ(translate_contents(ui, block.items[i].data.array)));
+ ADD_C(new_block, ARRAY_OBJ(translate_contents(ui, block.items[i].data.array, &arena)));
}
ADD_C(new_args, ARRAY_OBJ(new_block));
push_call(ui, name, new_args);
- api_free_array(new_block);
- return;
+ goto free_ret;
} else if (strequal(name, "cmdline_block_append")) {
- Array new_args = translate_firstarg(ui, args);
+ Array new_args = translate_firstarg(ui, args, &arena);
push_call(ui, name, new_args);
- api_free_array(new_args);
- return;
+ goto free_ret;
}
}
@@ -1022,19 +1024,18 @@ static void remote_ui_event(UI *ui, char *name, Array args)
if (data->wildmenu_active) {
Array new_args = data->call_buf;
Array items = args.items[0].data.array;
- Array new_items = ARRAY_DICT_INIT;
+ Array new_items = arena_array(&arena, items.size);
for (size_t i = 0; i < items.size; i++) {
- ADD(new_items, copy_object(items.items[i].data.array.items[0]));
+ ADD_C(new_items, items.items[i].data.array.items[0]);
}
ADD_C(new_args, ARRAY_OBJ(new_items));
push_call(ui, "wildmenu_show", new_args);
- api_free_array(new_items);
if (args.items[1].data.integer != -1) {
Array new_args2 = data->call_buf;
ADD_C(new_args2, args.items[1]);
push_call(ui, "wildmenu_select", new_args2);
}
- return;
+ goto free_ret;
}
} else if (strequal(name, "popupmenu_select")) {
if (data->wildmenu_active) {
@@ -1048,6 +1049,10 @@ static void remote_ui_event(UI *ui, char *name, Array args)
}
push_call(ui, name, args);
+ return;
+
+free_ret:
+ arena_mem_free(arena_finish(&arena));
}
static void remote_ui_inspect(UI *ui, Dictionary *info)
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index 8b7e01e1c3..17930dca85 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -100,7 +100,7 @@ void raw_line(Integer grid, Integer row, Integer startcol,
FUNC_API_NOEXPORT FUNC_API_COMPOSITOR_IMPL;
void event(char *name, Array args)
- FUNC_API_NOEXPORT;
+ FUNC_API_NOEXPORT FUNC_API_COMPOSITOR_IMPL;
void win_pos(Integer grid, Window win, Integer startrow,
Integer startcol, Integer width, Integer height)
@@ -121,7 +121,7 @@ void msg_set_pos(Integer grid, Integer row, Boolean scrolled, String sep_char)
void win_viewport(Integer grid, Window win, Integer topline,
Integer botline, Integer curline, Integer curcol,
Integer line_count)
- FUNC_API_SINCE(7) FUNC_API_REMOTE_ONLY;
+ FUNC_API_SINCE(7) FUNC_API_BRIDGE_IMPL;
void win_extmark(Integer grid, Window win, Integer ns_id, Integer mark_id,
Integer row, Integer col)
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index ce91c1b4af..95c9919522 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -79,19 +79,17 @@
/// @param[out] err Error details, if any
/// @return Highlight definition map
/// @see nvim_get_hl_by_id
-Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Error *err)
+Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Arena *arena, Error *err)
FUNC_API_SINCE(3)
{
Dictionary result = ARRAY_DICT_INIT;
int id = syn_name2id(name.data);
if (id == 0) {
- api_set_error(err, kErrorTypeException, "Invalid highlight name: %s",
- name.data);
+ api_set_error(err, kErrorTypeException, "Invalid highlight name: %s", name.data);
return result;
}
- result = nvim_get_hl_by_id(id, rgb, err);
- return result;
+ return nvim_get_hl_by_id(id, rgb, arena, err);
}
/// Gets a highlight definition by id. |hlID()|
@@ -100,17 +98,16 @@ Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Error *err)
/// @param[out] err Error details, if any
/// @return Highlight definition map
/// @see nvim_get_hl_by_name
-Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err)
+Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Arena *arena, Error *err)
FUNC_API_SINCE(3)
{
Dictionary dic = ARRAY_DICT_INIT;
if (syn_get_final_id((int)hl_id) == 0) {
- api_set_error(err, kErrorTypeException,
- "Invalid highlight id: %" PRId64, hl_id);
+ api_set_error(err, kErrorTypeException, "Invalid highlight id: %" PRId64, hl_id);
return dic;
}
int attrcode = syn_id2attr((int)hl_id);
- return hl_get_attr_by_id(attrcode, rgb, err);
+ return hl_get_attr_by_id(attrcode, rgb, arena, err);
}
/// Gets a highlight group by name
@@ -122,10 +119,10 @@ Integer nvim_get_hl_id_by_name(String name)
return syn_check_group(name.data, name.size);
}
-Dictionary nvim__get_hl_defs(Integer ns_id, Error *err)
+Dictionary nvim__get_hl_defs(Integer ns_id, Arena *arena, Error *err)
{
if (ns_id == 0) {
- return get_global_hl_defs();
+ return get_global_hl_defs(arena);
}
abort();
}
@@ -175,6 +172,10 @@ void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err)
FUNC_API_SINCE(7)
{
int hl_id = syn_check_group(name.data, name.size);
+ if (hl_id == 0) {
+ api_set_error(err, kErrorTypeException, "Invalid highlight name: %s", name.data);
+ return;
+ }
int link_id = -1;
HlAttrs attrs = dict2hlattrs(val, true, &link_id, err);
@@ -198,7 +199,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.
@@ -335,9 +336,9 @@ Integer nvim_input(String keys)
/// mouse input in a GUI. The deprecated pseudokey form
/// ("<LeftMouse><col,row>") of |nvim_input()| has the same limitation.
///
-/// @param button Mouse button: one of "left", "right", "middle", "wheel".
+/// @param button Mouse button: one of "left", "right", "middle", "wheel", "move".
/// @param action For ordinary buttons, one of "press", "drag", "release".
-/// For the wheel, one of "up", "down", "left", "right".
+/// For the wheel, one of "up", "down", "left", "right". Ignored for "move".
/// @param modifier String of modifiers each represented by a single char.
/// The same specifiers are used as for a key press, except
/// that the "-" separator is optional, so "C-A-", "c-a"
@@ -364,6 +365,8 @@ void nvim_input_mouse(String button, String action, String modifier, Integer gri
code = KE_RIGHTMOUSE;
} else if (strequal(button.data, "wheel")) {
code = KE_MOUSEDOWN;
+ } else if (strequal(button.data, "move")) {
+ code = KE_MOUSEMOVE;
} else {
goto error;
}
@@ -380,7 +383,7 @@ void nvim_input_mouse(String button, String action, String modifier, Integer gri
} else {
goto error;
}
- } else {
+ } else if (code != KE_MOUSEMOVE) {
if (strequal(action.data, "press")) {
// pass
} else if (strequal(action.data, "drag")) {
@@ -1419,10 +1422,10 @@ Dictionary nvim_get_mode(void)
/// @param mode Mode short-name ("n", "i", "v", ...)
/// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key is always zero.
-ArrayOf(Dictionary) nvim_get_keymap(uint64_t channel_id, String mode)
+ArrayOf(Dictionary) nvim_get_keymap(String mode)
FUNC_API_SINCE(3)
{
- return keymap_array(mode, NULL, channel_id == LUA_INTERNAL_CALL);
+ return keymap_array(mode, NULL);
}
/// Sets a global |mapping| for the given mode.
@@ -1479,14 +1482,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 +1548,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 +1563,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 +1632,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 +1645,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 +1667,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 +1679,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 +1757,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 +1770,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 +1783,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 +1809,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;
}
@@ -1928,7 +1935,7 @@ void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Di
}
/// NB: if your UI doesn't use hlstate, this will not return hlstate first time
-Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Error *err)
+Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, Error *err)
{
Array ret = ARRAY_DICT_INIT;
@@ -1952,13 +1959,14 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Error *err)
|| col < 0 || col >= g->cols) {
return ret;
}
+ ret = arena_array(arena, 3);
size_t off = g->line_offset[(size_t)row] + (size_t)col;
- ADD(ret, STRING_OBJ(cstr_to_string((char *)g->chars[off])));
+ ADD_C(ret, STRING_OBJ(cstr_as_string((char *)g->chars[off])));
int attr = g->attrs[off];
- ADD(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, err)));
+ ADD_C(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, arena, err)));
// will not work first time
if (!highlight_use_hlstate()) {
- ADD(ret, ARRAY_OBJ(hl_inspect(attr)));
+ ADD_C(ret, ARRAY_OBJ(hl_inspect(attr)));
}
return ret;
}
@@ -2040,7 +2048,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 +2096,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 +2104,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 +2236,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..40bd786e27 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;
@@ -437,9 +437,73 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
}
}
+static bool parse_title(FloatConfig* out, String s)
+{
+ // The raw title is going to be at most the length of the string.
+ char* out_title_raw = xcalloc(sizeof(char), s.size + 1);
+ size_t out_cursor = 0;
+
+ char* data = s.data;
+
+ size_t out_hlrec_nalloc = 4;
+ stl_hlrec_t* out_hlrec = xcalloc(sizeof(stl_hlrec_t), out_hlrec_nalloc);
+ out_hlrec[0].start = (char*) out_title_raw;
+ out_hlrec[0].userhl = 0;
+ size_t out_hl_cur = 1;
+
+ char hlbuf[128];
+ size_t hlbuf_cur = 0;
+
+ int hl;
+
+ for (size_t i = 0; i < s.size; i ++) {
+ if (data[i] == '\\' && i < s.size - 1) {
+ i ++;
+ out_title_raw[out_cursor++] = data[i];
+ } else if (
+ data[i] == '%' &&
+ i < s.size - 1 && data[i + 1] == '#') {
+ i += 2;
+ while (i < s.size && data[i] != '#') {
+ if (hlbuf_cur < sizeof(hlbuf) - 1) {
+ hlbuf[hlbuf_cur ++] = data[i];
+ }
+ i ++;
+ }
+ hlbuf[hlbuf_cur++] = 0;
+ hl = syn_check_group(hlbuf, strlen(hlbuf));
+ hlbuf_cur = 0;
+
+ if (out_hl_cur >= out_hlrec_nalloc - 1) { // Leave room for last.
+ out_hlrec =
+ xrealloc(out_hlrec, sizeof(stl_hlrec_t) * (out_hlrec_nalloc *= 2));
+ }
+
+ out_hlrec[out_hl_cur].start = (out_title_raw + out_cursor);
+ out_hlrec[out_hl_cur++].userhl = -hl;
+ } else {
+ out_title_raw[out_cursor++] = data[i];
+ }
+ }
+
+ out->n_title = out_cursor;
+ out_title_raw[out_cursor++] = 0;
+ out_hlrec[out_hl_cur] = (stl_hlrec_t) { 0, 0 };
+ out->title_hl = out_hlrec;
+ out->title = out_title_raw;
+
+ return true;
+}
+
static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig, bool reconf,
bool new_win, Error *err)
{
+ xfree(fconfig->title);
+ xfree(fconfig->title_hl);
+ fconfig->title_hl = NULL;
+ fconfig->n_title = 0;
+ fconfig->title = NULL;
+
bool has_relative = false, relative_is_win = false;
if (config->relative.type == kObjectTypeString) {
// ignore empty string, to match nvim_win_get_config
@@ -634,5 +698,44 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
}
}
+ if (HAS_KEY(config->title)) {
+ if (!parse_title(fconfig, config->title.data.string)) {
+ api_set_error(err, kErrorTypeValidation,
+ "Invalid value of 'title' key.");
+ goto free_and_fail;
+ }
+ } else if (config->title.type == kObjectTypeString) {
+ api_set_error(err, kErrorTypeValidation, "'title' must be a string");
+ return false;
+ }
+
+ if (HAS_KEY(config->title_position)) {
+ if (config->title_position.type != kObjectTypeString) {
+ api_set_error(err, kErrorTypeValidation,
+ "Invalid value of 'title_position' key");
+ goto free_and_fail;
+ }
+
+ if (striequal(config->title_position.data.string.data, "left")) {
+ fconfig->title_pos = kTitleLeft;
+ } else if (striequal(config->title_position.data.string.data, "center")) {
+ fconfig->title_pos = kTitleCenter;
+ } else if (striequal(config->title_position.data.string.data, "right")) {
+ fconfig->title_pos = kTitleRight;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "Invalid value for 'title_position'");
+ goto free_and_fail;
+ }
+ }
+
return true;
+
+free_and_fail:
+ xfree(fconfig->title);
+ xfree(fconfig->title_hl);
+ fconfig->n_title = 0;
+ fconfig->title_hl = NULL;
+ fconfig->title = NULL;
+ return false;
}
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..02e3a99aab 100644
--- a/src/nvim/arglist.c
+++ b/src/nvim/arglist.c
@@ -79,13 +79,14 @@ void alist_expand(int *fnum_list, int fnum_len)
{
char *save_p_su = p_su;
+ char **old_arg_files = xmalloc(sizeof(*old_arg_files) * GARGCOUNT);
+
// Don't use 'suffixes' here. This should work like the shell did the
// expansion. Also, the vimrc file isn't read yet, thus the user
// can't set the options.
p_su = empty_option;
- char **old_arg_files = xmalloc(sizeof(*old_arg_files) * GARGCOUNT);
for (int i = 0; i < GARGCOUNT; i++) {
- old_arg_files[i] = vim_strsave(GARGLIST[i].ae_fname);
+ old_arg_files[i] = xstrdup(GARGLIST[i].ae_fname);
}
int old_arg_count = GARGCOUNT;
char **new_arg_files;
@@ -157,7 +158,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 +203,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 +227,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 +245,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 +298,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;
@@ -308,6 +309,50 @@ static void alist_add_list(int count, char **files, int after, bool will_edit)
}
}
+/// Delete the file names in "alist_ga" from the argument list.
+static void arglist_del_files(garray_T *alist_ga)
+{
+ regmatch_T regmatch;
+
+ // Delete the items: use each item as a regexp and find a match in the
+ // argument list.
+ regmatch.rm_ic = p_fic; // ignore case when 'fileignorecase' is set
+ for (int i = 0; i < alist_ga->ga_len && !got_int; i++) {
+ char *p = ((char **)alist_ga->ga_data)[i];
+ p = file_pat_to_reg_pat(p, NULL, NULL, false);
+ if (p == NULL) {
+ break;
+ }
+ regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
+ if (regmatch.regprog == NULL) {
+ xfree(p);
+ break;
+ }
+
+ bool didone = false;
+ for (int match = 0; match < ARGCOUNT; match++) {
+ if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]), (colnr_T)0)) {
+ didone = true;
+ xfree(ARGLIST[match].ae_fname);
+ memmove(ARGLIST + match, ARGLIST + match + 1,
+ (size_t)(ARGCOUNT - match - 1) * sizeof(aentry_T));
+ ALIST(curwin)->al_ga.ga_len--;
+ if (curwin->w_arg_idx > match) {
+ curwin->w_arg_idx--;
+ }
+ match--;
+ }
+ }
+
+ vim_regfree(regmatch.regprog);
+ xfree(p);
+ if (!didone) {
+ semsg(_(e_nomatch2), ((char **)alist_ga->ga_data)[i]);
+ }
+ }
+ ga_clear(alist_ga);
+}
+
/// @param str
/// @param what
/// AL_SET: Redefine the argument list to 'str'.
@@ -324,8 +369,6 @@ static int do_arglist(char *str, int what, int after, bool will_edit)
garray_T new_ga;
int exp_count;
char **exp_files;
- char *p;
- int match;
int arg_escaped = true;
// Set default argument for ":argadd" command.
@@ -341,46 +384,7 @@ static int do_arglist(char *str, int what, int after, bool will_edit)
get_arglist(&new_ga, str, arg_escaped);
if (what == AL_DEL) {
- regmatch_T regmatch;
- bool didone;
-
- // Delete the items: use each item as a regexp and find a match in the
- // argument list.
- regmatch.rm_ic = p_fic; // ignore case when 'fileignorecase' is set
- for (int i = 0; i < new_ga.ga_len && !got_int; i++) {
- p = ((char **)new_ga.ga_data)[i];
- p = file_pat_to_reg_pat(p, NULL, NULL, false);
- if (p == NULL) {
- break;
- }
- regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
- if (regmatch.regprog == NULL) {
- xfree(p);
- break;
- }
-
- didone = false;
- for (match = 0; match < ARGCOUNT; match++) {
- if (vim_regexec(&regmatch, alist_name(&ARGLIST[match]), (colnr_T)0)) {
- didone = true;
- xfree(ARGLIST[match].ae_fname);
- memmove(ARGLIST + match, ARGLIST + match + 1,
- (size_t)(ARGCOUNT - match - 1) * sizeof(aentry_T));
- ALIST(curwin)->al_ga.ga_len--;
- if (curwin->w_arg_idx > match) {
- curwin->w_arg_idx--;
- }
- match--;
- }
- }
-
- vim_regfree(regmatch.regprog);
- xfree(p);
- if (!didone) {
- semsg(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]);
- }
- }
- ga_clear(&new_ga);
+ arglist_del_files(&new_ga);
} else {
int i = expand_wildcards(new_ga.ga_len, new_ga.ga_data,
&exp_count, &exp_files,
@@ -471,28 +475,31 @@ void ex_args(exarg_T *eap)
ex_next(eap);
} else if (eap->cmdidx == CMD_args) {
// ":args": list arguments.
- if (ARGCOUNT > 0) {
- char **items = xmalloc(sizeof(char_u *) * (size_t)ARGCOUNT);
- // Overwrite the command, for a short list there is no scrolling
- // required and no wait_return().
- gotocmdline(true);
- for (int i = 0; i < ARGCOUNT; i++) {
- items[i] = alist_name(&ARGLIST[i]);
- }
- list_in_columns(items, ARGCOUNT, curwin->w_arg_idx);
- xfree(items);
+ if (ARGCOUNT <= 0) {
+ return;
}
+
+ 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);
+
+ for (int i = 0; i < ARGCOUNT; i++) {
+ items[i] = alist_name(&ARGLIST[i]);
+ }
+ list_in_columns(items, ARGCOUNT, curwin->w_arg_idx);
+ xfree(items);
} else if (eap->cmdidx == CMD_arglocal) {
garray_T *gap = &curwin->w_alist->al_ga;
// ":argslocal": make a local copy of the global argument list.
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++;
}
}
@@ -626,7 +633,7 @@ void ex_argdedupe(exarg_T *eap FUNC_ATTR_UNUSED)
{
for (int i = 0; i < ARGCOUNT; i++) {
for (int j = i + 1; j < ARGCOUNT; j++) {
- if (FNAMECMP(ARGLIST[i].ae_fname, ARGLIST[j].ae_fname) == 0) {
+ if (path_fnamecmp(ARGLIST[i].ae_fname, ARGLIST[j].ae_fname) == 0) {
xfree(ARGLIST[j].ae_fname);
memmove(ARGLIST + j, ARGLIST + j + 1,
(size_t)(ARGCOUNT - j - 1) * sizeof(aentry_T));
@@ -742,7 +749,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 +1081,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 +1102,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,36 +1130,38 @@ 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;
- if (argvars[0].v_type != VAR_UNKNOWN) {
- if (argvars[1].v_type == VAR_UNKNOWN) {
- arglist = ARGLIST;
- argcount = ARGCOUNT;
- } else if (argvars[1].v_type == VAR_NUMBER
- && tv_get_number(&argvars[1]) == -1) {
- arglist = GARGLIST;
- argcount = GARGCOUNT;
- } else {
- win_T *wp = find_win_by_nr_or_id(&argvars[1]);
- if (wp != NULL) {
- // Use the argument list of the specified window
- arglist = WARGLIST(wp);
- argcount = WARGCOUNT(wp);
- }
- }
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = NULL;
- int idx = (int)tv_get_number_chk(&argvars[0], NULL);
- if (arglist != NULL && idx >= 0 && idx < argcount) {
- rettv->vval.v_string = xstrdup((const char *)alist_name(&arglist[idx]));
- } else if (idx == -1) {
- get_arglist_as_rettv(arglist, argcount, rettv);
- }
- } else {
+ if (argvars[0].v_type == VAR_UNKNOWN) {
get_arglist_as_rettv(ARGLIST, ARGCOUNT, rettv);
+ return;
+ }
+
+ if (argvars[1].v_type == VAR_UNKNOWN) {
+ arglist = ARGLIST;
+ argcount = ARGCOUNT;
+ } else if (argvars[1].v_type == VAR_NUMBER
+ && tv_get_number(&argvars[1]) == -1) {
+ arglist = GARGLIST;
+ argcount = GARGCOUNT;
+ } else {
+ win_T *wp = find_win_by_nr_or_id(&argvars[1]);
+ if (wp != NULL) {
+ // Use the argument list of the specified window
+ arglist = WARGLIST(wp);
+ argcount = WARGCOUNT(wp);
+ }
+ }
+
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = NULL;
+ int idx = (int)tv_get_number_chk(&argvars[0], NULL);
+ if (arglist != NULL && idx >= 0 && idx < argcount) {
+ rettv->vval.v_string = xstrdup((const char *)alist_name(&arglist[idx]));
+ } else if (idx == -1) {
+ get_arglist_as_rettv(arglist, argcount, rettv);
}
}
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 579c6c029f..9d37647a4e 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)) {
@@ -2206,7 +2214,7 @@ bool has_autocmd(event_T event, char *sfname, buf_T *buf)
#ifdef BACKSLASH_IN_FILENAME
// Replace all backslashes with forward slashes. This makes the
// autocommand patterns portable between Unix and Windows.
- sfname = vim_strsave(sfname);
+ sfname = xstrdup(sfname);
forward_slash(sfname);
forward_slash(fname);
#endif
@@ -2388,7 +2396,7 @@ bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT
}
// if pattern is "<buffer>", special handling is needed which uses curbuf
- // for pattern "<buffer=N>, FNAMECMP() will work fine
+ // for pattern "<buffer=N>, path_fnamecmp() will work fine
if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0) {
buflocal_buf = curbuf;
}
@@ -2396,12 +2404,12 @@ bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT
// Check if there is an autocommand with the given pattern.
for (; ap != NULL; ap = ap->next) {
// only use a pattern when it has not been removed and has commands.
- // For buffer-local autocommands, FNAMECMP() works fine.
+ // For buffer-local autocommands, path_fnamecmp() works fine.
if (ap->pat != NULL && ap->cmds != NULL
&& (group == AUGROUP_ALL || ap->group == group)
&& (pattern == NULL
|| (buflocal_buf == NULL
- ? FNAMECMP(ap->pat, pattern) == 0
+ ? path_fnamecmp(ap->pat, pattern) == 0
: ap->buflocal_nr == buflocal_buf->b_fnum))) {
retval = true;
break;
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..1cc68c9cee 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.
@@ -2725,7 +2733,7 @@ void buflist_list(exarg_T *eap)
IObuff[len++] = ' ';
} while (--i > 0 && len < IOSIZE - 18);
if (vim_strchr(eap->arg, 't') && buf->b_last_used) {
- undo_fmt_time(IObuff + len, (size_t)(IOSIZE - len), buf->b_last_used);
+ undo_fmt_time((char_u *)IObuff + len, (size_t)(IOSIZE - len), buf->b_last_used);
} else {
vim_snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), _("line %" PRId64),
buf == curbuf ? (int64_t)curwin->w_cursor.lnum : (int64_t)buflist_findlnum(buf));
@@ -2957,7 +2965,7 @@ static bool otherfile_buf(buf_T *buf, char *ffname, FileID *file_id_p, bool file
if (ffname == NULL || *ffname == NUL || buf->b_ffname == NULL) {
return true;
}
- if (FNAMECMP(ffname, buf->b_ffname) == 0) {
+ if (path_fnamecmp(ffname, buf->b_ffname) == 0) {
return false;
}
{
@@ -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;
@@ -3327,7 +3335,7 @@ static bool value_change(char *str, char **last)
FUNC_ATTR_WARN_UNUSED_RESULT
{
if ((str == NULL) != (*last == NULL)
- || (str != NULL && *last != NULL && STRCMP(str, *last) != 0)) {
+ || (str != NULL && *last != NULL && strcmp(str, *last) != 0)) {
xfree(*last);
if (str == NULL) {
*last = NULL;
@@ -3693,7 +3701,7 @@ static int chk_modeline(linenr_T lnum, int flags)
int retval = OK;
prev = -1;
- for (s = (char *)ml_get(lnum); *s != NUL; s++) {
+ for (s = ml_get(lnum); *s != NUL; s++) {
if (prev == -1 || ascii_isspace(prev)) {
if ((prev != -1 && STRNCMP(s, "ex:", (size_t)3) == 0)
|| STRNCMP(s, "vi:", (size_t)3) == 0) {
@@ -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;
@@ -4139,7 +4159,7 @@ bool buf_contents_changed(buf_T *buf)
if (buf->b_ml.ml_line_count == curbuf->b_ml.ml_line_count) {
differ = false;
for (linenr_T lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) {
- if (STRCMP(ml_get_buf(buf, lnum, false), ml_get(lnum)) != 0) {
+ if (strcmp(ml_get_buf(buf, lnum, false), ml_get(lnum)) != 0) {
differ = true;
break;
}
@@ -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 15b964f5ed..19b698537b 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -48,25 +48,23 @@ typedef struct {
#define GETFILE_SUCCESS(x) ((x) <= 0)
#define MODIFIABLE(buf) (buf->b_p_ma)
-/*
- * Flags for w_valid.
- * These are set when something in a window structure becomes invalid, except
- * when the cursor is moved. Call check_cursor_moved() before testing one of
- * the flags.
- * These are reset when that thing has been updated and is valid again.
- *
- * Every function that invalidates one of these must call one of the
- * invalidate_* functions.
- *
- * w_valid is supposed to be used only in screen.c. From other files, use the
- * functions that set or reset the flags.
- *
- * VALID_BOTLINE VALID_BOTLINE_AP
- * on on w_botline valid
- * off on w_botline approximated
- * off off w_botline not valid
- * on off not possible
- */
+// Flags for w_valid.
+// These are set when something in a window structure becomes invalid, except
+// when the cursor is moved. Call check_cursor_moved() before testing one of
+// the flags.
+// These are reset when that thing has been updated and is valid again.
+//
+// Every function that invalidates one of these must call one of the
+// invalidate_* functions.
+//
+// w_valid is supposed to be used only in screen.c. From other files, use the
+// functions that set or reset the flags.
+//
+// VALID_BOTLINE VALID_BOTLINE_AP
+// on on w_botline valid
+// off on w_botline approximated
+// off off w_botline not valid
+// on off not possible
#define VALID_WROW 0x01 // w_wrow (window row) is valid
#define VALID_WCOL 0x02 // w_wcol (window col) is valid
#define VALID_VIRTCOL 0x04 // w_virtcol (file col) is valid
@@ -112,31 +110,25 @@ typedef uint64_t disptick_T; // display tick type
#include "nvim/sign_defs.h"
#include "nvim/terminal.h" // for Terminal
-/*
- * The taggy struct is used to store the information about a :tag command.
- */
+// 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;
typedef struct buffheader buffheader_T;
-/*
- * structure used to store one block of the stuff/redo/recording buffers
- */
+// structure used to store one block of the stuff/redo/recording buffers
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)
};
-/*
- * header used for the stuff buffer and the redo buffer
- */
+// header used for the stuff buffer and the redo buffer
struct buffheader {
buffblock_T bh_first; // first (dummy) block of list
buffblock_T *bh_curr; // buffblock for appending
@@ -149,49 +141,47 @@ typedef struct {
buffheader_T sr_old_redobuff;
} save_redo_T;
-/*
- * Structure that contains all options that are local to a window.
- * Used twice in a window: for the current buffer and for all buffers.
- * Also used in wininfo_T.
- */
+// Structure that contains all options that are local to a window.
+// Used twice in a window: for the current buffer and for all buffers.
+// Also used in wininfo_T.
typedef struct {
int wo_arab;
#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 +191,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 +205,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 +215,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 +235,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 +243,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'
@@ -268,16 +258,14 @@ typedef struct {
#define w_p_script_ctx w_onebuf_opt.wo_script_ctx
} winopt_T;
-/*
- * Window info stored with a buffer.
- *
- * Two types of info are kept for a buffer which are associated with a
- * specific window:
- * 1. Each window can have a different line number associated with a buffer.
- * 2. The window-local options for a buffer work in a similar way.
- * The window-info is kept in a list at b_wininfo. It is kept in
- * most-recently-used order.
- */
+// Window info stored with a buffer.
+//
+// Two types of info are kept for a buffer which are associated with a
+// specific window:
+// 1. Each window can have a different line number associated with a buffer.
+// 2. The window-local options for a buffer work in a similar way.
+// The window-info is kept in a list at b_wininfo. It is kept in
+// most-recently-used order.
struct wininfo_S {
wininfo_T *wi_next; // next entry or NULL for last entry
wininfo_T *wi_prev; // previous entry or NULL for first entry
@@ -290,12 +278,10 @@ struct wininfo_S {
int wi_changelistidx; // copy of w_changelistidx
};
-/*
- * Argument list: Array of file names.
- * Used for the global argument list and the argument lists local to a window.
- *
- * TODO: move struct arglist to another header
- */
+// Argument list: Array of file names.
+// Used for the global argument list and the argument lists local to a window.
+//
+// TODO(neovim): move struct arglist to another header
typedef struct arglist {
garray_T al_ga; // growarray with the array of file names
int al_refcount; // number of windows using this arglist
@@ -308,8 +294,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
@@ -321,12 +307,10 @@ typedef struct argentry {
#define ARGCOUNT (ALIST(curwin)->al_ga.ga_len)
#define WARGCOUNT(wp) (ALIST(wp)->al_ga.ga_len)
-/*
- * Used for the typeahead buffer: typebuf.
- */
+// 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[]
@@ -347,16 +331,14 @@ typedef struct {
String save_inputbuf;
} tasave_T;
-/*
- * Structure used for mappings and abbreviations.
- */
+// Structure used for mappings and abbreviations.
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 +348,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.
@@ -414,9 +396,7 @@ struct stl_item {
typedef struct qf_info_S qf_info_T;
-/*
- * Used for :syntime: timing of executing a syntax pattern.
- */
+// Used for :syntime: timing of executing a syntax pattern.
typedef struct {
proftime_T total; // total time used
proftime_T slowest; // time of slowest call
@@ -424,10 +404,8 @@ typedef struct {
long match; // nr of times matched
} syn_time_T;
-/*
- * These are items normally related to a buffer. But when using ":ownsyntax"
- * a window may have its own instance.
- */
+// These are items normally related to a buffer. But when using ":ownsyntax"
+// a window may have its own instance.
typedef struct {
hashtab_T b_keywtab; // syntax keywords hash table
hashtab_T b_keywtab_ic; // idem, ignore case
@@ -440,14 +418,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 +454,20 @@ 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'
+#define SPO_CAMEL 0x1
+#define SPO_NPBUFFER 0x2
+ unsigned b_p_spo_flags; // 'spelloptions' flags
+ 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
@@ -514,13 +495,11 @@ EXTERN int curbuf_splice_pending INIT(= 0);
// Maximum number of maphash blocks we will have
#define MAX_MAPHASH 256
-/*
- * buffer: structure that holds information about one file
- *
- * Several windows can share a single Buffer
- * A buffer is unallocated if there is no memfile for it.
- * A buffer is new if the associated file has never been loaded yet.
- */
+// buffer: structure that holds information about one file
+//
+// Several windows can share a single Buffer
+// A buffer is unallocated if there is no memfile for it.
+// A buffer is new if the associated file has never been loaded yet.
struct file_buffer {
handle_T handle; // unique id for the buffer (buffer number)
@@ -570,15 +549,13 @@ struct file_buffer {
varnumber_T b_last_changedtick_pum; // b:changedtick when TextChangedP was
// last triggered.
- bool b_saving; /* Set to true if we are in the middle of
- saving the buffer. */
+ bool b_saving; // Set to true if we are in the middle of
+ // saving the buffer.
- /*
- * Changes to a buffer require updating of the display. To minimize the
- * work, remember changes made and update everything at once.
- */
- bool b_mod_set; /* true when there are changes since the last
- time the display was updated */
+ // Changes to a buffer require updating of the display. To minimize the
+ // work, remember changes made and update everything at once.
+ bool b_mod_set; // true when there are changes since the last
+ // time the display was updated
linenr_T b_mod_top; // topmost lnum that was changed
linenr_T b_mod_bot; // lnum below last changed line, AFTER the
// change
@@ -600,7 +577,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()
@@ -609,17 +586,13 @@ struct file_buffer {
fmark_T b_last_insert; // where Insert mode was left
fmark_T b_last_change; // position of last change: '. mark
- /*
- * the changelist contains old change positions
- */
+ // the changelist contains old change positions
fmark_T b_changelist[JUMPLISTSIZE];
int b_changelistlen; // number of active entries
bool b_new_change; // set by u_savecommon()
- /*
- * Character table, only used in charset.c for 'iskeyword'
- * bitset with 4*64=256 bits: 1 bit per character 0-255.
- */
+ // Character table, only used in charset.c for 'iskeyword'
+ // bitset with 4*64=256 bits: 1 bit per character 0-255.
uint64_t b_chartab[4];
// Table used for mappings local to a buffer.
@@ -629,18 +602,14 @@ struct file_buffer {
mapblock_T *b_first_abbr;
// User commands local to the buffer.
garray_T b_ucmds;
- /*
- * start and end of an operator, also used for '[ and ']
- */
+ // start and end of an operator, also used for '[ and ']
pos_T b_op_start;
pos_T b_op_start_orig; // used for Insstart_orig
pos_T b_op_end;
bool b_marks_read; // Have we read ShaDa marks yet?
- /*
- * The following only used in undo.c.
- */
+ // The following only used in undo.c.
u_header_T *b_u_oldhead; // pointer to oldest header
u_header_T *b_u_newhead; // pointer to newest header; may not be valid
// if b_u_curhead is not NULL
@@ -653,10 +622,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
@@ -675,83 +642,83 @@ struct file_buffer {
#define KEYMAP_LOADED 2 // 'keymap' mappings have been loaded
garray_T b_kmap_ga; // the keymap table
- /*
- * Options local to a buffer.
- * They are here because their value depends on the type of file
- * or contents of the file being edited.
- */
+ // Options local to a buffer.
+ // They are here because their value depends on the type of file
+ // or contents of the file being edited.
bool b_p_initialized; // set when options initialized
LastSet b_p_script_ctx[BV_COUNT]; // SCTXs for buffer-local options
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 *b_p_tfu; ///< 'tagfunc'
+ char *b_p_cfu; ///< 'completefunc'
+ char *b_p_ofu; ///< 'omnifunc'
+ char *b_p_urf; ///< 'userregfunc'
+ char *b_p_umf; ///< 'usermarkfunc'
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
@@ -759,29 +726,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
@@ -824,8 +791,8 @@ struct file_buffer {
int b_ind_cpp_extern_c;
int b_ind_pragma;
- linenr_T b_no_eol_lnum; /* non-zero lnum when last line of next binary
- * write should not have an end-of-line */
+ linenr_T b_no_eol_lnum; // non-zero lnum when last line of next binary
+ // write should not have an end-of-line
int b_start_eol; // last line had eol when it was read
int b_start_ffc; // first char of 'ff' when edit started
@@ -836,20 +803,18 @@ struct file_buffer {
ScopeDictDictItem b_bufvar; ///< Variable for "b:" Dictionary.
dict_T *b_vars; ///< b: scope dictionary.
- /* When a buffer is created, it starts without a swap file. b_may_swap is
- * then set to indicate that a swap file may be opened later. It is reset
- * if a swap file could not be opened.
- */
+ // When a buffer is created, it starts without a swap file. b_may_swap is
+ // then set to indicate that a swap file may be opened later. It is reset
+ // if a swap file could not be opened.
bool b_may_swap;
- bool b_did_warn; /* Set to true if user has been warned on first
- change of a read-only file */
-
- /* Two special kinds of buffers:
- * help buffer - used for help files, won't use a swap file.
- * 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_did_warn; // Set to true if user has been warned on first
+ // change of a read-only file
+
+ // Two special kinds of buffers:
+ // help buffer - used for help files, won't use a swap file.
+ // 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
// is "help")
bool b_spell; // True for a spell file buffer, most fields
// are not used! Use the B_SPELL macro to
@@ -908,25 +873,21 @@ struct file_buffer {
int b_diff_failed; // internal diff failed for this buffer
};
-/*
- * Stuff for diff mode.
- */
+// Stuff for diff mode.
#define DB_COUNT 8 // up to four buffers can be diff'ed
-/*
- * Each diffblock defines where a block of lines starts in each of the buffers
- * and how many lines it occupies in that buffer. When the lines are missing
- * in the buffer the df_count[] is zero. This is all counted in
- * buffer lines.
- * There is always at least one unchanged line in between the diffs.
- * Otherwise it would have been included in the diff above or below it.
- * df_lnum[] + df_count[] is the lnum below the change. When in one buffer
- * lines have been inserted, in the other buffer df_lnum[] is the line below
- * the insertion and df_count[] is zero. When appending lines at the end of
- * the buffer, df_lnum[] is one beyond the end!
- * This is using a linked list, because the number of differences is expected
- * to be reasonable small. The list is sorted on lnum.
- */
+// Each diffblock defines where a block of lines starts in each of the buffers
+// and how many lines it occupies in that buffer. When the lines are missing
+// in the buffer the df_count[] is zero. This is all counted in
+// buffer lines.
+// There is always at least one unchanged line in between the diffs.
+// Otherwise it would have been included in the diff above or below it.
+// df_lnum[] + df_count[] is the lnum below the change. When in one buffer
+// lines have been inserted, in the other buffer df_lnum[] is the line below
+// the insertion and df_count[] is zero. When appending lines at the end of
+// the buffer, df_lnum[] is one beyond the end!
+// This is using a linked list, because the number of differences is expected
+// to be reasonable small. The list is sorted on lnum.
typedef struct diffblock_S diff_T;
struct diffblock_S {
diff_T *df_next;
@@ -966,30 +927,26 @@ struct tabpage_S {
char *tp_prevdir; ///< Previous directory.
};
-/*
- * Structure to cache info for displayed lines in w_lines[].
- * Each logical line has one entry.
- * The entry tells how the logical line is currently displayed in the window.
- * This is updated when displaying the window.
- * 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,
- * the entries can only be used to count the number of displayed lines used.
- * wl_lnum and wl_lastlnum are invalid too.
- */
+// Structure to cache info for displayed lines in w_lines[].
+// Each logical line has one entry.
+// The entry tells how the logical line is currently displayed in the window.
+// This is updated when displaying the window.
+// 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,
+// 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;
-/*
- * Windows are kept in a tree of frames. Each frame has a column (FR_COL)
- * or row (FR_ROW) layout or is a leaf, which has a window.
- */
+// Windows are kept in a tree of frames. Each frame has a column (FR_COL)
+// or row (FR_ROW) layout or is a leaf, which has a window.
struct frame_S {
char fr_layout; // FR_LEAF, FR_COL or FR_ROW
int fr_width;
@@ -1010,12 +967,10 @@ struct frame_S {
#define FR_ROW 1 // frame with a row of windows
#define FR_COL 2 // frame with a column of windows
-/*
- * Struct used for highlighting 'hlsearch' matches, matches defined by
- * ":match" and matches defined by match functions.
- * For 'hlsearch' there is one pattern for all windows. For ":match" and the
- * match functions there is a different pattern for each window.
- */
+// Struct used for highlighting 'hlsearch' matches, matches defined by
+// ":match" and matches defined by match functions.
+// For 'hlsearch' there is one pattern for all windows. For ":match" and the
+// match functions there is a different pattern for each window.
typedef struct {
regmmatch_T rm; // points to the regexp program; contains last found
// match (may continue in next line)
@@ -1051,10 +1006,8 @@ struct posmatch {
linenr_T botlnum; ///< bottom buffer line
};
-/*
- * matchitem_T provides a linked list for storing match items for ":match" and
- * the match functions.
- */
+// matchitem_T provides a linked list for storing match items for ":match" and
+// the match functions.
typedef struct matchitem matchitem_T;
struct matchitem {
matchitem_T *next;
@@ -1095,6 +1048,12 @@ typedef enum {
kWinStyleMinimal, /// Minimal UI: no number column, eob markers, etc
} WinStyle;
+typedef enum {
+ kTitleLeft = 0,
+ kTitleCenter,
+ kTitleRight
+} TitlePosition;
+
typedef struct {
Window window;
lpos_T bufpos;
@@ -1112,6 +1071,11 @@ typedef struct {
int border_hl_ids[8];
int border_attr[8];
bool noautocmd;
+
+ stl_hlrec_t* title_hl;
+ char* title;
+ size_t n_title;
+ TitlePosition title_pos;
} FloatConfig;
#define FLOAT_CONFIG_INIT ((FloatConfig){ .height = 0, .width = 0, \
@@ -1121,7 +1085,11 @@ typedef struct {
.focusable = true, \
.zindex = kZIndexFloatDefault, \
.style = kWinStyleUnused, \
- .noautocmd = false })
+ .noautocmd = false, \
+ .title_hl = NULL, \
+ .title = NULL, \
+ .n_title = 0, \
+ .title_pos = kTitleLeft})
// Structure to store last cursor position and topline. Used by check_lnums()
// and reset_lnums().
@@ -1221,16 +1189,15 @@ struct window_S {
int diff;
int msgsep;
int eob;
+ int colorcol;
} w_p_fcs_chars;
- /*
- * "w_topline", "w_leftcol" and "w_skipcol" specify the offsets for
- * displaying the buffer.
- */
- 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() */
+ // "w_topline", "w_leftcol" and "w_skipcol" specify the offsets for
+ // displaying the buffer.
+ 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()
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
@@ -1242,9 +1209,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
@@ -1280,26 +1248,20 @@ struct window_S {
int w_height_outer;
int w_width_outer;
- /*
- * === start of cached values ====
- */
- /*
- * Recomputing is minimized by storing the result of computations.
- * Use functions in screen.c to check if they are valid and to update.
- * w_valid is a bitfield of flags, which indicate if specific values are
- * valid or need to be recomputed.
- */
+ // === start of cached values ====
+
+ // Recomputing is minimized by storing the result of computations.
+ // Use functions in screen.c to check if they are valid and to update.
+ // w_valid is a bitfield of flags, which indicate if specific values are
+ // valid or need to be recomputed.
int w_valid;
- pos_T w_valid_cursor; /* last known position of w_cursor, used
- to adjust w_valid */
+ pos_T w_valid_cursor; // last known position of w_cursor, used to adjust w_valid
colnr_T w_valid_leftcol; // last known w_leftcol
bool w_viewport_invalid;
- /*
- * w_cline_height is the number of physical lines taken by the buffer line
- * that the cursor is on. We use this to avoid extra calls to plines_win().
- */
+ // w_cline_height is the number of physical lines taken by the buffer line
+ // that the cursor is on. We use this to avoid extra calls to plines_win().
int w_cline_height; // current size of cursor line
bool w_cline_folded; // cursor line is folded
@@ -1312,11 +1274,9 @@ struct window_S {
// more than one screen line or when
// w_leftcol is non-zero
- /*
- * w_wrow and w_wcol specify the cursor position in the window.
- * This is related to positions in the window, not in the display or
- * buffer, thus w_wrow is relative to w_winrow.
- */
+ // w_wrow and w_wcol specify the cursor position in the window.
+ // This is related to positions in the window, not in the display or
+ // buffer, thus w_wrow is relative to w_winrow.
int w_wrow, w_wcol; // cursor position in window
linenr_T w_botline; // number of the line below the bottom of
@@ -1325,16 +1285,14 @@ struct window_S {
int w_filler_rows; // number of filler rows at the end of the
// window
- /*
- * Info about the lines currently in the window is remembered to avoid
- * recomputing it every time. The allocated size of w_lines[] is Rows.
- * Only the w_lines_valid entries are actually valid.
- * When the display is up-to-date w_lines[0].wl_lnum is equal to w_topline
- * and w_lines[w_lines_valid - 1].wl_lnum is equal to w_botline.
- * Between changing text and updating the display w_lines[] represents
- * what is currently displayed. wl_valid is reset to indicated this.
- * This is used for efficient redrawing.
- */
+ // Info about the lines currently in the window is remembered to avoid
+ // recomputing it every time. The allocated size of w_lines[] is Rows.
+ // Only the w_lines_valid entries are actually valid.
+ // When the display is up-to-date w_lines[0].wl_lnum is equal to w_topline
+ // and w_lines[w_lines_valid - 1].wl_lnum is equal to w_botline.
+ // Between changing text and updating the display w_lines[] represents
+ // what is currently displayed. wl_valid is reset to indicated this.
+ // This is used for efficient redrawing.
int w_lines_valid; // number of valid entries
wline_T *w_lines;
@@ -1347,13 +1305,11 @@ struct window_S {
// column being used
int w_scwidth; // width of 'signcolumn'
- /*
- * === end of cached values ===
- */
+ // === end of cached values ===
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
@@ -1365,7 +1321,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-^)
@@ -1407,17 +1363,13 @@ struct window_S {
ScopeDictDictItem w_winvar; ///< Variable for "w:" dictionary.
dict_T *w_vars; ///< Dictionary with w: variables.
- /*
- * The w_prev_pcmark field is used to check whether we really did jump to
- * a new line after setting the w_pcmark. If not, then we revert to
- * using the previous w_pcmark.
- */
+ // The w_prev_pcmark field is used to check whether we really did jump to
+ // a new line after setting the w_pcmark. If not, then we revert to
+ // using the previous w_pcmark.
pos_T w_pcmark; // previous context mark
pos_T w_prev_pcmark; // previous w_pcmark
- /*
- * the jumplist contains old cursor positions
- */
+ // the jumplist contains old cursor positions
xfmark_T w_jumplist[JUMPLISTSIZE];
int w_jumplistlen; // number of active entries
int w_jumplistidx; // current position
@@ -1427,12 +1379,10 @@ struct window_S {
matchitem_T *w_match_head; // head of match list
int w_next_match_id; // next match ID
- /*
- * the tagstack grows from 0 upwards:
- * entry 0: older
- * entry 1: newer
- * entry 2: newest
- */
+ // the tagstack grows from 0 upwards:
+ // entry 0: older
+ // entry 1: newer
+ // entry 2: newest
taggy_T w_tagstack[TAGSTACKSIZE]; // the tag stack
int w_tagstackidx; // idx just below active entry
int w_tagstacklen; // number of tags on stack
@@ -1443,17 +1393,14 @@ struct window_S {
bool w_floating; ///< whether the window is floating
FloatConfig w_float_config;
- /*
- * w_fraction is the fractional row of the cursor within the window, from
- * 0 at the top row to FRACTION_MULT at the last row.
- * w_prev_fraction_row was the actual cursor row when w_fraction was last
- * calculated.
- */
+ // w_fraction is the fractional row of the cursor within the window, from
+ // 0 at the top row to FRACTION_MULT at the last row.
+ // w_prev_fraction_row was the actual cursor row when w_fraction was last
+ // calculated.
int w_fraction;
int w_prev_fraction_row;
- linenr_T w_nrwidth_line_count; /* line count when ml_nrwidth_width
- * was computed. */
+ linenr_T w_nrwidth_line_count; // line count when ml_nrwidth_width was computed.
int w_nrwidth_width; // nr of chars to print line count.
qf_info_T *w_llist; // Location list for this window
@@ -1476,4 +1423,4 @@ struct window_S {
#define CHANGEDTICK(buf) \
(=== Include buffer.h & use buf_(get|set|inc) _changedtick ===)
-#endif // NVIM_BUFFER_DEFS_H
+#endif // NVIM_BUFFER_DEFS_H
diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c
index 14973502ab..1b3c0bc28f 100644
--- a/src/nvim/buffer_updates.c
+++ b/src/nvim/buffer_updates.c
@@ -285,14 +285,13 @@ void buf_updates_send_changes(buf_T *buf, linenr_T firstline, int64_t num_added,
args.items[7] = INTEGER_OBJ((Integer)deleted_codeunits);
}
textlock++;
- Object res = nlua_call_ref(cb.on_lines, "lines", args, true, NULL);
+ Object res = nlua_call_ref(cb.on_lines, "lines", args, false, NULL);
textlock--;
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
buffer_update_callbacks_free(cb);
keep = false;
}
- api_free_object(res);
}
if (keep) {
kv_A(buf->update_callbacks, j++) = kv_A(buf->update_callbacks, i);
@@ -335,7 +334,7 @@ void buf_updates_send_splice(buf_T *buf, int start_row, colnr_T start_col, bcoun
ADD_C(args, INTEGER_OBJ(new_byte));
textlock++;
- Object res = nlua_call_ref(cb.on_bytes, "bytes", args, true, NULL);
+ Object res = nlua_call_ref(cb.on_bytes, "bytes", args, false, NULL);
textlock--;
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
@@ -371,14 +370,13 @@ void buf_updates_changedtick(buf_T *buf)
textlock++;
Object res = nlua_call_ref(cb.on_changedtick, "changedtick",
- args, true, NULL);
+ args, false, NULL);
textlock--;
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
buffer_update_callbacks_free(cb);
keep = false;
}
- api_free_object(res);
}
if (keep) {
kv_A(buf->update_callbacks, j++) = kv_A(buf->update_callbacks, i);
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 5184dc0689..6cd971cd74 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,16 +534,67 @@ 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) {
@@ -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 = 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 = 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 = 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 = 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,7 +826,7 @@ 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));
fixpos = false;
@@ -801,9 +852,9 @@ 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);
+ ml_add_deleted_len((char *)curbuf->b_ml.ml_line_ptr, oldlen);
newp = oldp; // use same allocated memory
} else { // need to allocate a new line
newp = xmalloc((size_t)(oldlen + 1 - count));
@@ -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 = xstrdup(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 = xstrdup(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 {
@@ -1068,7 +1119,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// Skip preprocessor directives, unless they are recognised as comments.
if (lead_len == 0 && ptr[0] == '#') {
while (ptr[0] == '#' && curwin->w_cursor.lnum > 1) {
- ptr = (char *)ml_get(--curwin->w_cursor.lnum);
+ ptr = ml_get(--curwin->w_cursor.lnum);
}
newindent = get_indent();
}
@@ -1130,7 +1181,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
if ((pos = findmatch(NULL, '(')) != NULL) {
curwin->w_cursor.lnum = pos->lnum;
newindent = get_indent();
- ptr = (char *)get_cursor_line_ptr();
+ ptr = get_cursor_line_ptr();
}
}
// If last character is '{' do indent, without
@@ -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;
}
}
@@ -1159,7 +1210,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
} else {
was_backslashed = false;
}
- ptr = (char *)ml_get(++curwin->w_cursor.lnum);
+ ptr = ml_get(++curwin->w_cursor.lnum);
}
if (was_backslashed) {
newindent = 0; // Got to end of file
@@ -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;
@@ -1414,7 +1465,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// blank-out any other chars from the old leader.
while (--p >= leader) {
- int l = utf_head_off((char_u *)leader, (char_u *)p);
+ int l = utf_head_off(leader, p);
if (l > 1) {
p -= 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 = xstrdup(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 = xstrnsave(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..693ff90179 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;
}
@@ -789,7 +789,7 @@ bool vim_iswordc_buf(const int c, buf_T *const buf)
bool vim_iswordp(const char_u *const p)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- return vim_iswordp_buf(p, curbuf);
+ return vim_iswordp_buf((char *)p, curbuf);
}
/// Just like vim_iswordc_buf() but uses a pointer to the (multi-byte)
@@ -799,13 +799,13 @@ bool vim_iswordp(const char_u *const p)
/// @param buf buffer whose keywords to use
///
/// @return true if "p" points to a keyword character.
-bool vim_iswordp_buf(const char_u *const p, buf_T *const buf)
+bool vim_iswordp_buf(const char *const p, buf_T *const buf)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- int c = *p;
+ int c = (uint8_t)(*p);
if (MB_BYTE2LEN(c) > 1) {
- c = utf_ptr2char((char *)p);
+ c = utf_ptr2char(p);
}
return vim_iswordc_buf(c, buf);
}
@@ -829,8 +829,8 @@ bool vim_isfilec(int c)
bool vim_isfilec_or_wc(int c)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- char_u buf[2];
- buf[0] = (char_u)c;
+ char buf[2];
+ buf[0] = (char)c;
buf[1] = NUL;
return vim_isfilec(c) || c == ']' || path_has_wildcard(buf);
}
@@ -905,15 +905,15 @@ bool in_win_border(win_T *wp, colnr_T vcol)
/// @param end
void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end)
{
- char_u *ptr; // points to current char
- char_u *posptr; // points to char at pos->col
+ char *ptr; // points to current char
+ char *posptr; // points to char at pos->col
int incr;
int head;
long *vts = wp->w_buffer->b_p_vts_array;
int ts = (int)wp->w_buffer->b_p_ts;
colnr_T vcol = 0;
- char_u *line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, false); // start of the line
+ char *line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, false); // start of the line
if (pos->col == MAXCOL) {
// continue until the NUL
@@ -930,17 +930,21 @@ 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;
+ int c = (uint8_t)(*ptr);
// make sure we don't go past the end of the line
if (c == NUL) {
@@ -956,7 +960,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
// For utf-8, if the byte is >= 0x80, need to look at
// further bytes to find the cell width.
if (c >= 0x80) {
- incr = utf_ptr2cells((char *)ptr);
+ incr = utf_ptr2cells(ptr);
} else {
incr = g_chartab[c] & CT_CELL_MASK;
}
@@ -966,7 +970,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
// cells wide.
if ((incr == 2)
&& wp->w_p_wrap
- && (MB_BYTE2LEN(*ptr) > 1)
+ && (MB_BYTE2LEN((uint8_t)(*ptr)) > 1)
&& in_win_border(wp, vcol)) {
incr++;
head = 1;
@@ -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) && (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 = 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
@@ -1066,10 +1076,10 @@ void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *e
colnr_T endadd = 0;
// Cannot put the cursor on part of a wide character.
- char_u *ptr = ml_get_buf(wp->w_buffer, pos->lnum, false);
+ char *ptr = ml_get_buf(wp->w_buffer, pos->lnum, false);
if (pos->col < (colnr_T)STRLEN(ptr)) {
- int c = utf_ptr2char((char *)ptr + pos->col);
+ int c = utf_ptr2char(ptr + pos->col);
if ((c != TAB) && vim_isprintc(c)) {
endadd = (colnr_T)(char2cells(c) - 1);
if (coladd > endadd) {
@@ -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,14 +1168,14 @@ 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
@@ -1175,10 +1185,10 @@ intptr_t getwhitecols_curline(void)
return getwhitecols(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,16 +1329,16 @@ 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.
///
-/// @param[out] pp A pointer to a pointer to char_u.
+/// @param[out] pp A pointer to a pointer to char.
/// It will be advanced past the read number.
/// @param[out] nr Number read from the string.
///
@@ -1345,7 +1355,7 @@ bool try_getdigits(char **pp, intmax_t *nr)
/// Gets a number from a string and skips over it.
///
-/// @param[out] pp Pointer to a pointer to char_u.
+/// @param[out] pp Pointer to a pointer to char.
/// It will be advanced past the read number.
/// @param strict Abort on overflow.
/// @param def Default value, if parsing fails or overflow occurs.
@@ -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';
}
@@ -1453,14 +1463,14 @@ bool vim_isblankline(char_u *lbuf)
/// @param strict If true, fail if the number has unexpected trailing
/// alphanumeric chars: *len is set to 0 and nothing else is
/// returned.
-void vim_str2nr(const char_u *const start, int *const prep, int *const len, const int what,
+void vim_str2nr(const char *const start, int *const prep, int *const len, const int what,
varnumber_T *const nptr, uvarnumber_T *const unptr, const int maxlen,
const bool strict)
FUNC_ATTR_NONNULL_ARG(1)
{
- const char *ptr = (const char *)start;
+ const char *ptr = start;
#define STRING_ENDED(ptr) \
- (!(maxlen == 0 || (int)((ptr) - (const char *)start) < maxlen))
+ (!(maxlen == 0 || (int)((ptr) - start) < maxlen))
int pre = 0; // default is decimal
const bool negative = (ptr[0] == '-');
uvarnumber_T un = 0;
@@ -1512,7 +1522,7 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, cons
} else if ((what & (STR2NR_HEX | STR2NR_OCT | STR2NR_OOCT | STR2NR_BIN))
&& !STRING_ENDED(ptr + 1) && ptr[0] == '0' && ptr[1] != '8'
&& ptr[1] != '9') {
- pre = (char_u)ptr[1];
+ pre = (uint8_t)ptr[1];
// Detect hexadecimal: 0x or 0X followed by hex digit.
if ((what & STR2NR_HEX)
&& !STRING_ENDED(ptr + 2)
@@ -1600,7 +1610,7 @@ vim_str2nr_hex:
vim_str2nr_proceed:
// Check for an alphanumeric character immediately following, that is
// most likely a typo.
- if (strict && ptr - (const char *)start != maxlen && ASCII_ISALNUM(*ptr)) {
+ if (strict && ptr - start != maxlen && ASCII_ISALNUM(*ptr)) {
return;
}
@@ -1609,7 +1619,7 @@ vim_str2nr_proceed:
}
if (len != NULL) {
- *len = (int)(ptr - (const char *)start);
+ *len = (int)(ptr - start);
}
if (nptr != NULL) {
@@ -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..3e9edea372 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"
@@ -65,8 +66,8 @@ static int compl_selected;
static int sort_func_compare(const void *s1, const void *s2)
{
- char_u *p1 = *(char_u **)s1;
- char_u *p2 = *(char_u **)s2;
+ char *p1 = *(char **)s1;
+ char *p2 = *(char **)s2;
if (*p1 != '<' && *p2 == '<') {
return -1;
@@ -74,7 +75,7 @@ static int sort_func_compare(const void *s1, const void *s2)
if (*p1 == '<' && *p2 != '<') {
return 1;
}
- return STRCMP(p1, p2);
+ return strcmp(p1, p2);
}
static void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char **files, int options)
@@ -176,29 +177,29 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
ui_flush();
}
- i = (int)((char_u *)xp->xp_pattern - ccline->cmdbuff);
+ i = (int)(xp->xp_pattern - ccline->cmdbuff);
assert(ccline->cmdpos >= i);
xp->xp_pattern_len = (size_t)ccline->cmdpos - (size_t)i;
if (type == WILD_NEXT || type == WILD_PREV) {
// Get next/previous match for a previous expanded pattern.
- p2 = ExpandOne(xp, NULL, NULL, 0, type);
+ p2 = (char_u *)ExpandOne(xp, NULL, NULL, 0, type);
} else {
// Translate string into pattern and expand it.
- p1 = addstar((char_u *)xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
+ p1 = (char_u *)addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
const int use_options = (options
| WILD_HOME_REPLACE
| WILD_ADD_SLASH
| WILD_SILENT
| (escape ? WILD_ESCAPE : 0)
| (p_wic ? WILD_ICASE : 0));
- p2 = ExpandOne(xp, p1, vim_strnsave(&ccline->cmdbuff[i], xp->xp_pattern_len),
- use_options, type);
+ p2 = (char_u *)ExpandOne(xp, (char *)p1, xstrnsave(&ccline->cmdbuff[i], xp->xp_pattern_len),
+ use_options, type);
xfree(p1);
// xp->xp_pattern might have been modified by ExpandOne (for example,
// in lua completion), so recompute the pattern index and length
- i = (int)((char_u *)xp->xp_pattern - ccline->cmdbuff);
+ i = (int)(xp->xp_pattern - ccline->cmdbuff);
xp->xp_pattern_len = (size_t)ccline->cmdpos - (size_t)i;
// Longest match: make sure it is not shorter, happens with :help.
@@ -219,7 +220,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
difflen = (int)STRLEN(p2) - (int)(xp->xp_pattern_len);
if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen) {
realloc_cmdbuff(ccline->cmdlen + difflen + 4);
- xp->xp_pattern = (char *)ccline->cmdbuff + i;
+ xp->xp_pattern = ccline->cmdbuff + i;
}
assert(ccline->cmdpos <= ccline->cmdlen);
memmove(&ccline->cmdbuff[ccline->cmdpos + difflen],
@@ -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 *get_next_or_prev_match(int mode, expand_T *xp, int *p_findex, char *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 xstrdup(findex == -1 ? orig_save : xp->xp_files[findex]);
+}
+
+/// Start the command-line expansion and get the matches.
+static char *ExpandOne_start(int mode, expand_T *xp, char *str, int options)
+{
+ int non_suf_match; // number without matching suffix
+ char *ss = NULL;
+
+ // Do the expansion.
+ if (ExpandFromContext(xp, (char_u *)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, (char_u *)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(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 = xstrdup(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
@@ -309,63 +458,25 @@ void cmdline_pum_cleanup(CmdlineInfo *cclp)
/// The variables xp->xp_context and xp->xp_backslash must have been set!
///
/// @param orig allocated copy of original of expanded string
-char_u *ExpandOne(expand_T *xp, char_u *str, char_u *orig, int options, int mode)
+char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
{
- char_u *ss = NULL;
+ char *ss = NULL;
static int findex;
- static char_u *orig_save = NULL; // kept value of orig
+ static char *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 *)"");
+ ss = xstrdup(orig_save ? orig_save : "");
} else if (mode == WILD_APPLY) {
- ss = vim_strsave(findex == -1 ? (orig_save ? orig_save : (char_u *)"") :
- (char_u *)xp->xp_files[findex]);
+ ss = xstrdup(findex == -1
+ ? (orig_save ? orig_save : "")
+ : xp->xp_files[findex]);
}
// free old names
@@ -385,93 +496,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 = find_longest_match(xp, options);
findex = -1; // next p_wc gets first one
}
@@ -544,7 +574,7 @@ int showmatches(expand_T *xp, int wildmenu)
if (xp->xp_numfiles == -1) {
set_expand_context(xp);
- i = expand_cmdline(xp, ccline->cmdbuff, ccline->cmdpos,
+ i = expand_cmdline(xp, (char_u *)ccline->cmdbuff, ccline->cmdpos,
&num_files, &files_found);
showtail = expand_showtail(xp);
if (i != EXPAND_OK) {
@@ -573,7 +603,7 @@ int showmatches(expand_T *xp, int wildmenu)
.pum_kind = NULL,
};
}
- char_u *endpos = (char_u *)(showtail ? sm_gettail(xp->xp_pattern, true) : xp->xp_pattern);
+ char *endpos = (showtail ? sm_gettail(xp->xp_pattern, true) : xp->xp_pattern);
if (ui_has(kUICmdline)) {
compl_startcol = (int)(endpos - ccline->cmdbuff);
} else {
@@ -641,12 +671,12 @@ 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);
msg_advance(maxlen + 3);
- msg_outtrans_long_attr(p + 2, HL_ATTR(HLF_D));
+ msg_outtrans_long_attr((char *)p + 2, HL_ATTR(HLF_D));
break;
}
for (j = maxlen - lastlen; --j >= 0;) {
@@ -662,33 +692,32 @@ 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();
msg_putchar('\n');
}
- ui_flush(); // show one line at a time
if (got_int) {
got_int = false;
break;
@@ -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;
@@ -775,13 +804,13 @@ static bool expand_showtail(expand_T *xp)
/// the name into allocated memory and prepend "^".
///
/// @param context EXPAND_FILES etc.
-char_u *addstar(char_u *fname, size_t len, int context)
+char *addstar(char *fname, size_t len, int context)
FUNC_ATTR_NONNULL_RET
{
- char_u *retval;
+ char *retval;
size_t i, j;
size_t new_len;
- char_u *tail;
+ char *tail;
int ends_in_star;
if (context != EXPAND_FILES
@@ -803,7 +832,7 @@ char_u *addstar(char_u *fname, size_t len, int context)
|| context == EXPAND_PACKADD
|| ((context == EXPAND_TAGS_LISTFILES || context == EXPAND_TAGS)
&& fname[0] == '/')) {
- retval = vim_strnsave(fname, len);
+ retval = xstrnsave(fname, len);
} else {
new_len = len + 2; // +2 for '^' at start, NUL at end
for (i = 0; i < len; i++) {
@@ -873,7 +902,7 @@ char_u *addstar(char_u *fname, size_t len, int context)
// $ could be anywhere in the tail.
// ` could be anywhere in the file name.
// When the name ends in '$' don't add a star, remove the '$'.
- tail = (char_u *)path_tail((char *)retval);
+ tail = path_tail(retval);
ends_in_star = (len > 0 && retval[len - 1] == '*');
#ifndef BACKSLASH_IN_FILENAME
for (ssize_t k = (ssize_t)len - 2; k >= 0; k--) {
@@ -885,8 +914,8 @@ char_u *addstar(char_u *fname, size_t len, int context)
#endif
if ((*retval != '~' || tail != retval)
&& !ends_in_star
- && vim_strchr((char *)tail, '$') == NULL
- && vim_strchr((char *)retval, '`') == NULL) {
+ && vim_strchr(tail, '$') == NULL
+ && vim_strchr(retval, '`') == NULL) {
retval[len++] = '*';
} else if (len > 0 && retval[len - 1] == '$') {
len--;
@@ -948,68 +977,26 @@ void set_expand_context(expand_T *xp)
xp->xp_context = EXPAND_NOTHING;
return;
}
- set_cmd_context(xp, ccline->cmdbuff, ccline->cmdlen, ccline->cmdpos, true);
+ set_cmd_context(xp, (char_u *)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(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:
@@ -1313,6 +1204,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
case CMD_folddoclosed:
case CMD_folddoopen:
case CMD_hide:
+ case CMD_horizontal:
case CMD_keepalt:
case CMD_keepjumps:
case CMD_keepmarks:
@@ -1348,14 +1240,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 +1282,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 +1389,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,10 +1422,10 @@ 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);
+ set_context_in_sign_cmd(xp, (char *)arg);
break;
case CMD_bdelete:
case CMD_bwipeout:
@@ -1561,7 +1452,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 +1498,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 +1509,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 +1530,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 +1593,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 +1654,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
@@ -1785,7 +1852,7 @@ void set_cmd_context(expand_T *xp, char_u *str, int len, int col, int use_ccline
set_context_for_expression(xp, (char *)str, CMD_SIZE);
} else if (use_ccline && ccline->input_fn) {
xp->xp_context = ccline->xp_context;
- xp->xp_pattern = (char *)ccline->cmdbuff;
+ xp->xp_pattern = ccline->cmdbuff;
xp->xp_arg = (char *)ccline->xp_arg;
} else {
while (nextcomm != NULL) {
@@ -1832,7 +1899,7 @@ int expand_cmdline(expand_T *xp, char_u *str, int col, int *matchcount, char ***
// add star to file name, or convert to regexp if not exp. files.
assert((str + col) - (char_u *)xp->xp_pattern >= 0);
xp->xp_pattern_len = (size_t)((str + col) - (char_u *)xp->xp_pattern);
- file_str = addstar((char_u *)xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
+ file_str = (char_u *)addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
if (p_wic) {
options += WILD_ICASE;
@@ -1848,6 +1915,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 *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 = xstrdup(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 +2032,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 +2125,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, (char *)pat, file, num_file, flags, options);
}
*file = NULL;
@@ -2010,7 +2143,7 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char ***f
if (xp->xp_context == EXPAND_SHELLCMD) {
*file = NULL;
- expand_shellcmd(pat, num_file, file, flags);
+ expand_shellcmd((char *)pat, num_file, file, flags);
return OK;
}
if (xp->xp_context == EXPAND_OLD_SETTING) {
@@ -2029,19 +2162,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 +2183,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 +2218,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);
@@ -2159,18 +2239,18 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, cha
{
int i;
size_t count = 0;
- char_u *str;
+ char *str;
// count the number of matching names
for (i = 0;; i++) {
- str = (char_u *)(*func)(xp, i);
+ str = (*func)(xp, i);
if (str == NULL) { // end of list
break;
}
if (*str == NUL) { // skip empty strings
continue;
}
- if (vim_regexec(regmatch, (char *)str, (colnr_T)0)) {
+ if (vim_regexec(regmatch, str, (colnr_T)0)) {
count++;
}
}
@@ -2184,20 +2264,20 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, cha
// copy the matching names into allocated memory
count = 0;
for (i = 0;; i++) {
- str = (char_u *)(*func)(xp, i);
+ str = (*func)(xp, i);
if (str == NULL) { // End of list.
break;
}
if (*str == NUL) { // Skip empty strings.
continue;
}
- if (vim_regexec(regmatch, (char *)str, (colnr_T)0)) {
+ if (vim_regexec(regmatch, str, (colnr_T)0)) {
if (escaped) {
- str = vim_strsave_escaped(str, (char_u *)" \t\\.");
+ str = (char *)vim_strsave_escaped((char_u *)str, (char_u *)" \t\\.");
} else {
- str = vim_strsave(str);
+ str = xstrdup(str);
}
- (*file)[count++] = (char *)str;
+ (*file)[count++] = str;
if (func == get_menu_names) {
// Test for separator added by get_menu_names().
str += STRLEN(str) - 1;
@@ -2214,8 +2294,7 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, cha
|| xp->xp_context == EXPAND_FUNCTIONS
|| xp->xp_context == EXPAND_USER_FUNC) {
// <SNR> functions should be sorted to the end.
- qsort((void *)(*file), (size_t)(*num_file), sizeof(char_u *),
- sort_func_compare);
+ qsort((void *)(*file), (size_t)(*num_file), sizeof(char *), sort_func_compare);
} else {
sort_strings(*file, *num_file);
}
@@ -2234,22 +2313,22 @@ static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, cha
/// *file will either be set to NULL or point to
/// allocated memory.
/// @param flagsarg is a combination of EW_* flags.
-static void expand_shellcmd(char_u *filepat, int *num_file, char ***file, int flagsarg)
+static void expand_shellcmd(char *filepat, int *num_file, char ***file, int flagsarg)
FUNC_ATTR_NONNULL_ALL
{
- char_u *pat;
+ char *pat;
int i;
- char_u *path = NULL;
+ char *path = NULL;
garray_T ga;
char *buf = xmalloc(MAXPATHL);
size_t l;
- char_u *s, *e;
+ char *s, *e;
int flags = flagsarg;
int ret;
bool did_curdir = false;
// for ":set path=" and ":set tags=" halve backslashes for escaped space
- pat = vim_strsave(filepat);
+ pat = xstrdup(filepat);
for (i = 0; pat[i]; i++) {
if (pat[i] == '\\' && pat[i + 1] == ' ') {
STRMOVE(pat + i, pat + i + 1);
@@ -2261,14 +2340,14 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char ***file, int fl
bool mustfree = false; // Track memory allocation for *path.
if (pat[0] == '.' && (vim_ispathsep(pat[1])
|| (pat[1] == '.' && vim_ispathsep(pat[2])))) {
- path = (char_u *)".";
+ path = ".";
} else {
// For an absolute name we don't use $PATH.
- if (!path_is_absolute(pat)) {
- path = (char_u *)vim_getenv("PATH");
+ if (!path_is_absolute((char_u *)pat)) {
+ path = vim_getenv("PATH");
}
if (path == NULL) {
- path = (char_u *)"";
+ path = "";
} else {
mustfree = true;
}
@@ -2281,7 +2360,7 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char ***file, int fl
hashtab_T found_ht;
hash_init(&found_ht);
for (s = path;; s = e) {
- e = (char_u *)vim_strchr((char *)s, ENV_SEPCHAR);
+ e = vim_strchr(s, ENV_SEPCHAR);
if (e == NULL) {
e = s + STRLEN(s);
}
@@ -2359,9 +2438,9 @@ static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T
FUNC_ATTR_NONNULL_ALL
{
CmdlineInfo *const ccline = get_cmdline_info();
- char_u keep = 0;
+ char keep = 0;
typval_T args[4];
- char_u *pat = NULL;
+ char *pat = NULL;
const sctx_T save_current_sctx = current_sctx;
if (xp->xp_arg == NULL || xp->xp_arg[0] == '\0' || xp->xp_line == NULL) {
@@ -2375,12 +2454,12 @@ static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T
ccline->cmdbuff[ccline->cmdlen] = 0;
}
- pat = vim_strnsave((char_u *)xp->xp_pattern, xp->xp_pattern_len);
+ pat = xstrnsave(xp->xp_pattern, xp->xp_pattern_len);
args[0].v_type = VAR_STRING;
args[1].v_type = VAR_STRING;
args[2].v_type = VAR_NUMBER;
args[3].v_type = VAR_UNKNOWN;
- args[0].vval.v_string = (char *)pat;
+ args[0].vval.v_string = pat;
args[1].vval.v_string = xp->xp_line;
args[2].vval.v_number = xp->xp_col;
@@ -2400,30 +2479,29 @@ static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T
/// Expand names with a function defined by the user.
static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***file)
{
- char_u *e;
+ char *e;
garray_T ga;
- char_u *const retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp, num_file,
- file);
+ char *const retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp, num_file,
+ file);
if (retstr == NULL) {
return FAIL;
}
ga_init(&ga, (int)sizeof(char *), 3);
- for (char_u *s = retstr; *s != NUL; s = e) {
- e = (char_u *)vim_strchr((char *)s, '\n');
+ for (char *s = retstr; *s != NUL; s = e) {
+ e = vim_strchr(s, '\n');
if (e == NULL) {
e = s + STRLEN(s);
}
- const char_u keep = *e;
+ const char keep = *e;
*e = NUL;
- const bool skip = xp->xp_pattern[0]
- && vim_regexec(regmatch, (char *)s, (colnr_T)0) == 0;
+ const bool skip = xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0;
*e = keep;
if (!skip) {
- GA_APPEND(char_u *, &ga, vim_strnsave(s, (size_t)(e - s)));
+ GA_APPEND(char *, &ga, xstrnsave(s, (size_t)(e - s)));
}
if (*e != NUL) {
@@ -2494,7 +2572,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);
@@ -2584,7 +2662,7 @@ int wildmenu_process_key(CmdlineInfo *cclp, int key, expand_T *xp)
// cursor
int found = false;
- int j = (int)((char_u *)xp->xp_pattern - cclp->cmdbuff);
+ int j = (int)(xp->xp_pattern - cclp->cmdbuff);
int i = 0;
while (--j > 0) {
// check for start of menu name
@@ -2639,7 +2717,7 @@ int wildmenu_process_key(CmdlineInfo *cclp, int key, expand_T *xp)
int found = false;
int j = cclp->cmdpos;
- int i = (int)((char_u *)xp->xp_pattern - cclp->cmdbuff);
+ int i = (int)(xp->xp_pattern - cclp->cmdbuff);
while (--j > i) {
j -= utf_head_off(cclp->cmdbuff, cclp->cmdbuff + j);
if (vim_ispathsep(cclp->cmdbuff[j])) {
@@ -2660,7 +2738,7 @@ int wildmenu_process_key(CmdlineInfo *cclp, int key, expand_T *xp)
int found = false;
int j = cclp->cmdpos - 1;
- int i = (int)((char_u *)xp->xp_pattern - cclp->cmdbuff);
+ int i = (int)(xp->xp_pattern - cclp->cmdbuff);
while (--j > i) {
j -= utf_head_off(cclp->cmdbuff, cclp->cmdbuff + j);
if (vim_ispathsep(cclp->cmdbuff[j])
@@ -2732,7 +2810,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 +2829,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;
@@ -2811,13 +2889,13 @@ void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
if (xpc.xp_context == EXPAND_SIGN) {
- set_context_in_sign_cmd(&xpc, (char_u *)xpc.xp_pattern);
+ set_context_in_sign_cmd(&xpc, xpc.xp_pattern);
xpc.xp_pattern_len = STRLEN(xpc.xp_pattern);
}
theend:
- pat = addstar((char_u *)xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context);
- ExpandOne(&xpc, pat, NULL, options, WILD_ALL_KEEP);
+ pat = (char_u *)addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context);
+ ExpandOne(&xpc, (char *)pat, NULL, options, WILD_ALL_KEEP);
tv_list_alloc_ret(rettv, xpc.xp_numfiles);
for (int i = 0; i < xpc.xp_numfiles; i++) {
diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c
index 13f97ba1e8..3747c91c4f 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];
@@ -186,7 +186,7 @@ static inline void clear_hist_entry(histentry_T *hisptr)
/// If 'move_to_front' is true, matching entry is moved to end of history.
///
/// @param move_to_front Move the entry to the front if it exists
-static int in_history(int type, char_u *str, int move_to_front, int sep)
+static int in_history(int type, char *str, int move_to_front, int sep)
{
int last_i = -1;
@@ -201,8 +201,8 @@ static int in_history(int type, char_u *str, int move_to_front, int sep)
// For search history, check that the separator character matches as
// well.
- char_u *p = history[type][i].hisstr;
- if (STRCMP(str, p) == 0
+ char *p = history[type][i].hisstr;
+ if (strcmp(str, p) == 0
&& (type != HIST_SEARCH || sep == p[STRLEN(p) + 1])) {
if (!move_to_front) {
return true;
@@ -276,7 +276,7 @@ static int last_maptick = -1; // last seen maptick
/// @param histype may be one of the HIST_ values.
/// @param in_map consider maptick when inside a mapping
/// @param sep separator character used (search hist)
-void add_to_history(int histype, char_u *new_entry, int in_map, int sep)
+void add_to_history(int histype, char *new_entry, int in_map, int sep)
{
histentry_T *hisptr;
@@ -313,10 +313,10 @@ void add_to_history(int histype, char_u *new_entry, int in_map, int sep)
// Store the separator after the NUL of the string.
size_t len = STRLEN(new_entry);
- hisptr->hisstr = vim_strnsave(new_entry, len + 2);
+ hisptr->hisstr = xstrnsave(new_entry, len + 2);
hisptr->timestamp = os_time();
hisptr->additional_elements = NULL;
- hisptr->hisstr[len + 1] = (char_u)sep;
+ hisptr->hisstr[len + 1] = (char)sep;
hisptr->hisnum = ++hisnum[histype];
if (histype == HIST_SEARCH && in_map) {
@@ -382,13 +382,13 @@ static int calc_hist_idx(int histype, int num)
/// Get a history entry by its index.
///
/// @param histype may be one of the HIST_ values.
-static char_u *get_history_entry(int histype, int idx)
+static char *get_history_entry(int histype, int idx)
{
idx = calc_hist_idx(histype, idx);
if (idx >= 0) {
return history[histype][idx].hisstr;
} else {
- return (char_u *)"";
+ return "";
}
}
@@ -438,7 +438,7 @@ static int del_history_entry(int histype, char_u *str)
if (hisptr->hisstr == NULL) {
break;
}
- if (vim_regexec(&regmatch, (char *)hisptr->hisstr, (colnr_T)0)) {
+ if (vim_regexec(&regmatch, hisptr->hisstr, (colnr_T)0)) {
found = true;
hist_free_entry(hisptr);
} else {
@@ -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;
@@ -509,7 +509,7 @@ void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
str = tv_get_string_buf(&argvars[1], buf);
if (*str != NUL) {
init_history();
- add_to_history(histype, (char_u *)str, false, NUL);
+ add_to_history(histype, (char *)str, false, NUL);
rettv->vval.v_number = true;
return;
}
@@ -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;
@@ -556,13 +556,13 @@ void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr)
idx = (int)tv_get_number_chk(&argvars[1], NULL);
}
// -1 on type error
- rettv->vval.v_string = (char *)vim_strsave(get_history_entry(type, idx));
+ rettv->vval.v_string = xstrdup(get_history_entry(type, idx));
}
rettv->v_type = VAR_STRING;
}
/// "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
@@ -643,14 +643,13 @@ void ex_history(exarg_T *eap)
msg_putchar('\n');
snprintf((char *)IObuff, IOSIZE, "%c%6d ", i == idx ? '>' : ' ',
hist[i].hisnum);
- if (vim_strsize((char *)hist[i].hisstr) > Columns - 10) {
- trunc_string((char *)hist[i].hisstr, (char *)IObuff + STRLEN(IObuff),
+ if (vim_strsize(hist[i].hisstr) > Columns - 10) {
+ trunc_string(hist[i].hisstr, (char *)IObuff + STRLEN(IObuff),
Columns - 10, IOSIZE - (int)STRLEN(IObuff));
} else {
STRCAT(IObuff, hist[i].hisstr);
}
msg_outtrans((char *)IObuff);
- ui_flush();
}
if (i == idx) {
break;
diff --git a/src/nvim/cmdhist.h b/src/nvim/cmdhist.h
index 797b79a5f0..8b7bb7ac24 100644
--- a/src/nvim/cmdhist.h
+++ b/src/nvim/cmdhist.h
@@ -22,7 +22,7 @@ typedef enum {
/// History entry definition
typedef struct hist_entry {
int hisnum; ///< Entry identifier number.
- char_u *hisstr; ///< Actual entry, separator char after the NUL.
+ char *hisstr; ///< Actual entry, separator char after the NUL.
Timestamp timestamp; ///< Time when entry was added.
list_T *additional_elements; ///< Additional entries from ShaDa file.
} histentry_T;
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..cd651fcf4c 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -101,7 +101,7 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
|| (VIsual_active && *p_sel != 'o')
|| ((get_ve_flags() & VE_ONEMORE) && wcol < MAXCOL);
- char_u *line = ml_get_buf(curbuf, pos->lnum, false);
+ char_u *line = (char_u *)ml_get_buf(curbuf, pos->lnum, false);
if (wcol >= MAXCOL) {
idx = (int)STRLEN(line) - 1 + one_more;
@@ -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, (char *)line, (char *)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
@@ -304,7 +308,7 @@ void check_pos(buf_T *buf, pos_T *pos)
}
if (pos->col > 0) {
- char_u *line = ml_get_buf(buf, pos->lnum, false);
+ char_u *line = (char_u *)ml_get_buf(buf, pos->lnum, false);
colnr_T len = (colnr_T)STRLEN(line);
if (pos->col > len) {
pos->col = len;
@@ -471,13 +475,13 @@ bool leftcol_changed(void)
if (retval) {
curwin->w_set_curswant = true;
}
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
return retval;
}
int gchar_cursor(void)
{
- return utf_ptr2char((char *)get_cursor_pos_ptr());
+ return utf_ptr2char(get_cursor_pos_ptr());
}
/// Write a character at the current cursor position.
@@ -485,18 +489,17 @@ int gchar_cursor(void)
void pchar_cursor(char_u c)
{
*(ml_get_buf(curbuf, curwin->w_cursor.lnum, true)
- + curwin->w_cursor.col) = c;
+ + curwin->w_cursor.col) = (char)c;
}
/// @return pointer to cursor line.
-char_u *get_cursor_line_ptr(void)
+char *get_cursor_line_ptr(void)
{
return ml_get_buf(curbuf, curwin->w_cursor.lnum, false);
}
/// @return pointer to cursor position.
-char_u *get_cursor_pos_ptr(void)
+char *get_cursor_pos_ptr(void)
{
- return ml_get_buf(curbuf, curwin->w_cursor.lnum, false) +
- curwin->w_cursor.col;
+ return ml_get_buf(curbuf, curwin->w_cursor.lnum, false) + curwin->w_cursor.col;
}
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..e91491e665 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -33,7 +33,7 @@ static char *debug_newval = NULL;
struct debuggy {
int dbg_nr; ///< breakpoint number
int dbg_type; ///< DBG_FUNC or DBG_FILE or DBG_EXPR
- char_u *dbg_name; ///< function, expression or file name
+ char *dbg_name; ///< function, expression or file name
regprog_T *dbg_prog; ///< regexp program
linenr_T dbg_lnum; ///< line number in function or file
int dbg_forceit; ///< ! used
@@ -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;
@@ -60,7 +60,7 @@ void do_debug(char_u *cmd)
bool typeahead_saved = false;
int save_ignore_script = 0;
int n;
- char_u *cmdline = NULL;
+ char *cmdline = NULL;
char *p;
char *tail = NULL;
static int last_cmd = 0;
@@ -129,8 +129,8 @@ void do_debug(char_u *cmd)
}
xfree(cmdline);
- cmdline = (char_u *)getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL,
- CALLBACK_NONE);
+ cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL,
+ CALLBACK_NONE);
if (typeahead_saved) {
restore_typeahead(&typeaheadbuf);
@@ -144,7 +144,7 @@ void do_debug(char_u *cmd)
// If this is a debug command, set "last_cmd".
// If not, reset "last_cmd".
// For a blank line use previous command.
- p = skipwhite((char *)cmdline);
+ p = skipwhite(cmdline);
if (*p != NUL) {
switch (*p) {
case 'c':
@@ -246,7 +246,7 @@ void do_debug(char_u *cmd)
do_showbacktrace(cmd);
} else {
p = skipwhite(p);
- do_setdebugtracelevel((char_u *)p);
+ do_setdebugtracelevel(p);
}
continue;
case CMD_UP:
@@ -266,7 +266,7 @@ void do_debug(char_u *cmd)
// don't debug this command
n = debug_break_level;
debug_break_level = -1;
- (void)do_cmdline((char *)cmdline, getexline, NULL, DOCMD_VERBOSE|DOCMD_EXCRESET);
+ (void)do_cmdline(cmdline, getexline, NULL, DOCMD_VERBOSE|DOCMD_EXCRESET);
debug_break_level = n;
}
lines_left = Rows - 1;
@@ -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;
@@ -306,9 +306,9 @@ static int get_maxbacktrace_level(char *sname)
return maxbacktrace;
}
-static void do_setdebugtracelevel(char_u *arg)
+static void do_setdebugtracelevel(char *arg)
{
- int level = atoi((char *)arg);
+ int level = atoi(arg);
if (*arg == '+' || level < 0) {
debug_backtrace_level += level;
} else {
@@ -335,7 +335,7 @@ static void do_checkbacktracelevel(void)
}
}
-static void do_showbacktrace(char_u *cmd)
+static void do_showbacktrace(char *cmd)
{
char *sname = estack_sfile(ESTACK_NONE);
int max = get_maxbacktrace_level(sname);
@@ -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;
@@ -470,7 +470,7 @@ static typval_T *eval_expr_no_emsg(struct debuggy *const bp)
{
// Disable error messages, a bad expression would make Vim unusable.
emsg_off++;
- typval_T *const tv = eval_expr((char *)bp->dbg_name);
+ typval_T *const tv = eval_expr(bp->dbg_name);
emsg_off--;
return tv;
}
@@ -482,9 +482,9 @@ static typval_T *eval_expr_no_emsg(struct debuggy *const bp)
///
/// @param arg
/// @param gap either &dbg_breakp or &prof_ga
-static int dbg_parsearg(char_u *arg, garray_T *gap)
+static int dbg_parsearg(char *arg, garray_T *gap)
{
- char *p = (char *)arg;
+ char *p = arg;
char *q;
bool here = false;
@@ -531,11 +531,11 @@ static int dbg_parsearg(char_u *arg, garray_T *gap)
}
if (bp->dbg_type == DBG_FUNC) {
- bp->dbg_name = vim_strsave((char_u *)p);
+ bp->dbg_name = xstrdup(p);
} else if (here) {
- bp->dbg_name = vim_strsave((char_u *)curbuf->b_ffname);
+ bp->dbg_name = xstrdup(curbuf->b_ffname);
} else if (bp->dbg_type == DBG_EXPR) {
- bp->dbg_name = vim_strsave((char_u *)p);
+ bp->dbg_name = xstrdup(p);
bp->dbg_val = eval_expr_no_emsg(bp);
} else {
// Expand the file name in the same way as do_source(). This means
@@ -551,10 +551,10 @@ static int dbg_parsearg(char_u *arg, garray_T *gap)
return FAIL;
}
if (*p != '*') {
- bp->dbg_name = (char_u *)fix_fname(p);
+ bp->dbg_name = fix_fname(p);
xfree(p);
} else {
- bp->dbg_name = (char_u *)p;
+ bp->dbg_name = p;
}
}
@@ -572,12 +572,12 @@ void ex_breakadd(exarg_T *eap)
gap = &prof_ga;
}
- if (dbg_parsearg((char_u *)eap->arg, gap) == OK) {
+ if (dbg_parsearg(eap->arg, gap) == OK) {
struct debuggy *bp = &DEBUGGY(gap, gap->ga_len);
bp->dbg_forceit = eap->forceit;
if (bp->dbg_type != DBG_EXPR) {
- char *pat = file_pat_to_reg_pat((char *)bp->dbg_name, NULL, NULL, false);
+ char *pat = file_pat_to_reg_pat(bp->dbg_name, NULL, NULL, false);
if (pat != NULL) {
bp->dbg_prog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
xfree(pat);
@@ -639,14 +639,14 @@ void ex_breakdel(exarg_T *eap)
del_all = true;
} else {
// ":breakdel {func|file|expr} [lnum] {name}"
- if (dbg_parsearg((char_u *)eap->arg, gap) == FAIL) {
+ if (dbg_parsearg(eap->arg, gap) == FAIL) {
return;
}
bp = &DEBUGGY(gap, gap->ga_len);
for (int i = 0; i < gap->ga_len; i++) {
bpi = &DEBUGGY(gap, i);
if (bp->dbg_type == bpi->dbg_type
- && STRCMP(bp->dbg_name, bpi->dbg_name) == 0
+ && strcmp(bp->dbg_name, bpi->dbg_name) == 0
&& (bp->dbg_lnum == bpi->dbg_lnum
|| (bp->dbg_lnum == 0
&& (best_lnum == 0
@@ -697,7 +697,7 @@ void ex_breaklist(exarg_T *eap)
for (int i = 0; i < dbg_breakp.ga_len; i++) {
struct debuggy *bp = &BREAKP(i);
if (bp->dbg_type == DBG_FILE) {
- home_replace(NULL, (char *)bp->dbg_name, (char *)NameBuff, MAXPATHL, true);
+ home_replace(NULL, bp->dbg_name, (char *)NameBuff, MAXPATHL, true);
}
if (bp->dbg_type != DBG_EXPR) {
smsg(_("%3d %s %s line %" PRId64),
@@ -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..778f9293fb 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -69,7 +69,7 @@ void bufhl_add_hl_pos_offset(buf_T *buf, int src_id, int hl_id, lpos_T pos_start
void decor_redraw(buf_T *buf, int row1, int row2, Decoration *decor)
{
if (row2 >= row1) {
- if (!decor || decor->hl_id || decor_has_sign(decor) || decor->conceal) {
+ if (!decor || decor->hl_id || decor_has_sign(decor) || decor->conceal || decor->spell) {
redraw_buf_range_later(buf, row1 + 1, row2 + 1);
}
}
@@ -116,6 +116,11 @@ void decor_free(Decoration *decor)
}
}
+void decor_state_free(DecorState *state)
+{
+ xfree(state->active.items);
+}
+
void clear_virttext(VirtText *text)
{
for (size_t i = 0; i < kv_size(*text); i++) {
@@ -306,6 +311,7 @@ next_mark:
bool conceal = 0;
int conceal_char = 0;
int conceal_attr = 0;
+ bool spell = false;
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange item = kv_A(state->active, i);
@@ -339,6 +345,9 @@ next_mark:
conceal_attr = item.attr_id;
}
}
+ if (active && item.decor.spell) {
+ spell = true;
+ }
if ((item.start_row == state->row && item.start_col <= col)
&& decor_virt_pos(item.decor)
&& item.decor.virt_text_pos == kVTOverlay && item.win_col == -1) {
@@ -355,6 +364,7 @@ next_mark:
state->conceal = conceal;
state->conceal_char = conceal_char;
state->conceal_attr = conceal_attr;
+ state->spell = spell;
return attr;
}
@@ -394,7 +404,7 @@ void decor_redraw_signs(buf_T *buf, int row, int *num_signs, SignTextAttrs sattr
}
if (j < SIGN_SHOW_MAX) {
sattrs[j] = (SignTextAttrs) {
- .text = decor->sign_text,
+ .text = (char *)decor->sign_text,
.hl_attr_id = decor->sign_hl_id == 0 ? 0 : syn_id2attr(decor->sign_hl_id),
.priority = decor->priority
};
@@ -547,7 +557,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 +568,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/decoration.h b/src/nvim/decoration.h
index 8f28442d41..bdbfd72a81 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -46,6 +46,7 @@ struct Decoration {
bool hl_eol;
bool virt_lines_above;
bool conceal;
+ bool spell;
// TODO(bfredl): style, etc
DecorPriority priority;
int col; // fixed col value, like win_col
@@ -61,8 +62,8 @@ struct Decoration {
bool ui_watched; // watched for win_extmark
};
#define DECORATION_INIT { KV_INITIAL_VALUE, KV_INITIAL_VALUE, 0, kVTEndOfLine, \
- kHlModeUnknown, false, false, false, false, DECOR_PRIORITY_BASE, \
- 0, 0, NULL, 0, 0, 0, 0, 0, false }
+ kHlModeUnknown, false, false, false, false, false, \
+ DECOR_PRIORITY_BASE, 0, 0, NULL, 0, 0, 0, 0, 0, false }
typedef struct {
int start_row;
@@ -90,6 +91,8 @@ typedef struct {
bool conceal;
int conceal_char;
int conceal_attr;
+
+ bool spell;
} DecorState;
EXTERN DecorState decor_state INIT(= { 0 });
diff --git a/src/nvim/decoration_provider.c b/src/nvim/decoration_provider.c
index 14c1238fa4..a11a4d2b04 100644
--- a/src/nvim/decoration_provider.c
+++ b/src/nvim/decoration_provider.c
@@ -7,6 +7,7 @@
#include "nvim/decoration.h"
#include "nvim/decoration_provider.h"
#include "nvim/highlight.h"
+#include "nvim/lib/kvec.h"
#include "nvim/lua/executor.h"
static kvec_t(DecorProvider) decor_providers = KV_INITIAL_VALUE;
@@ -14,7 +15,7 @@ static kvec_t(DecorProvider) decor_providers = KV_INITIAL_VALUE;
#define DECORATION_PROVIDER_INIT(ns_id) (DecorProvider) \
{ ns_id, false, LUA_NOREF, LUA_NOREF, \
LUA_NOREF, LUA_NOREF, LUA_NOREF, \
- LUA_NOREF, -1, false }
+ LUA_NOREF, -1, false, false }
static bool decor_provider_invoke(NS ns_id, const char *name, LuaRef ref, Array args,
bool default_true, char **perr)
@@ -47,11 +48,33 @@ static bool decor_provider_invoke(NS ns_id, const char *name, LuaRef ref, Array
return false;
}
+void decor_providers_invoke_spell(win_T *wp, int start_row, int start_col, int end_row, int end_col,
+ char **err)
+{
+ for (size_t i = 0; i < kv_size(decor_providers); i++) {
+ DecorProvider *p = &kv_A(decor_providers, i);
+ if (!p->active) {
+ continue;
+ }
+
+ if (p->spell_nav != LUA_NOREF) {
+ MAXSIZE_TEMP_ARRAY(args, 6);
+ ADD_C(args, INTEGER_OBJ(wp->handle));
+ ADD_C(args, INTEGER_OBJ(wp->w_buffer->handle));
+ ADD_C(args, INTEGER_OBJ(start_row));
+ ADD_C(args, INTEGER_OBJ(start_col));
+ ADD_C(args, INTEGER_OBJ(end_row));
+ ADD_C(args, INTEGER_OBJ(end_col));
+ decor_provider_invoke(p->ns_id, "spell", p->spell_nav, args, true, err);
+ }
+ }
+}
+
/// For each provider invoke the 'start' callback
///
/// @param[out] providers Decoration providers
/// @param[out] err Provider err
-void decor_providers_start(DecorProviders *providers, int type, char **err)
+void decor_providers_start(DecorProviders *providers, char **err)
{
kvi_init(*providers);
@@ -65,7 +88,6 @@ void decor_providers_start(DecorProviders *providers, int type, char **err)
if (p->redraw_start != LUA_NOREF) {
MAXSIZE_TEMP_ARRAY(args, 2);
ADD_C(args, INTEGER_OBJ((int)display_tick));
- ADD_C(args, INTEGER_OBJ(type));
active = decor_provider_invoke(p->ns_id, "start", p->redraw_start, args, true, err);
} else {
active = true;
@@ -116,8 +138,8 @@ void decor_providers_invoke_win(win_T *wp, DecorProviders *providers,
/// @param row Row to invoke line callback for
/// @param[out] has_decor Set when at least one provider invokes a line callback
/// @param[out] err Provider error
-void providers_invoke_line(win_T *wp, DecorProviders *providers, int row, bool *has_decor,
- char **err)
+void decor_providers_invoke_line(win_T *wp, DecorProviders *providers, int row, bool *has_decor,
+ char **err)
{
for (size_t k = 0; k < kv_size(*providers); k++) {
DecorProvider *p = kv_A(*providers, k);
@@ -215,6 +237,7 @@ void decor_provider_clear(DecorProvider *p)
NLUA_CLEAR_REF(p->redraw_win);
NLUA_CLEAR_REF(p->redraw_line);
NLUA_CLEAR_REF(p->redraw_end);
+ NLUA_CLEAR_REF(p->spell_nav);
p->active = false;
}
diff --git a/src/nvim/decoration_provider.h b/src/nvim/decoration_provider.h
index dd1ed6c581..852b1583b9 100644
--- a/src/nvim/decoration_provider.h
+++ b/src/nvim/decoration_provider.h
@@ -12,6 +12,7 @@ typedef struct {
LuaRef redraw_line;
LuaRef redraw_end;
LuaRef hl_def;
+ LuaRef spell_nav;
int hl_valid;
bool hl_cached;
} DecorProvider;
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 5485d528f7..c5092dc866 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 = xstrdup(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++) {
@@ -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;
}
@@ -750,7 +750,7 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
len = 0;
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
- for (char_u *s = ml_get_buf(buf, lnum, false); *s != NUL;) {
+ for (char_u *s = (char_u *)ml_get_buf(buf, lnum, false); *s != NUL;) {
if (diff_flags & DIFF_ICASE) {
int c;
char cbuf[MB_MAXBYTES + 1];
@@ -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.
@@ -824,9 +824,9 @@ static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
ga_init(&dio->dio_diff.dout_ga, sizeof(char *), 1000);
} else {
// We need three temp file names.
- dio->dio_orig.din_fname = vim_tempname();
- dio->dio_new.din_fname = vim_tempname();
- dio->dio_diff.dout_fname = vim_tempname();
+ dio->dio_orig.din_fname = (char_u *)vim_tempname();
+ dio->dio_new.din_fname = (char_u *)vim_tempname();
+ dio->dio_diff.dout_fname = (char_u *)vim_tempname();
if (dio->dio_orig.din_fname == NULL
|| dio->dio_new.din_fname == NULL
|| dio->dio_diff.dout_fname == NULL) {
@@ -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,
@@ -1178,9 +1178,9 @@ void ex_diffpatch(exarg_T *eap)
// We need two temp file names.
// Name of original temp file.
- char_u *tmp_orig = vim_tempname();
+ char_u *tmp_orig = (char_u *)vim_tempname();
// Name of patched temp file.
- char_u *tmp_new = vim_tempname();
+ char_u *tmp_new = (char_u *)vim_tempname();
if ((tmp_orig == NULL) || (tmp_new == NULL)) {
goto theend;
@@ -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,8 +1920,8 @@ 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 = xstrdup(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));
@@ -1970,23 +1968,23 @@ static bool diff_equal_char(const char_u *const p1, const char_u *const p2, int
/// @param s2 The second string
///
/// @return on-zero if the two strings are different.
-static int diff_cmp(char_u *s1, char_u *s2)
+static int diff_cmp(char *s1, char *s2)
{
if ((diff_flags & DIFF_IBLANK)
- && (*(char_u *)skipwhite((char *)s1) == NUL || *skipwhite((char *)s2) == NUL)) {
+ && (*(char_u *)skipwhite(s1) == NUL || *skipwhite(s2) == NUL)) {
return 0;
}
if ((diff_flags & (DIFF_ICASE | ALL_WHITE_DIFF)) == 0) {
- return STRCMP(s1, s2);
+ return strcmp(s1, s2);
}
if ((diff_flags & DIFF_ICASE) && !(diff_flags & ALL_WHITE_DIFF)) {
return mb_stricmp((const char *)s1, (const char *)s2);
}
- char *p1 = (char *)s1;
- char *p2 = (char *)s2;
+ char *p1 = s1;
+ char *p2 = s2;
// Ignore white space changes and possibly ignore case.
while (*p1 != NUL && *p2 != NUL) {
@@ -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 = xstrdup(ml_get_buf(wp->w_buffer, lnum, false));
int idx = diff_buf_idx(wp->w_buffer);
if (idx == DB_COUNT) {
@@ -2324,8 +2322,7 @@ 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 = 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 +2334,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;
@@ -2380,11 +2377,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(line_org, (char *)p1);
+ p2 -= utf_head_off(line_new, (char *)p2);
if (!diff_equal_char(p1, p2, &l)) {
break;
@@ -2513,7 +2510,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 +2564,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 +2717,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 = xstrdup(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..8e31d3feab 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
@@ -1932,13 +1932,13 @@ void f_digraph_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
int code = digraph_get(digraphs[0], digraphs[1], false);
- char_u buf[NUMBUFLEN];
- buf[utf_char2bytes(code, (char *)buf)] = NUL;
- rettv->vval.v_string = (char *)vim_strsave(buf);
+ char buf[NUMBUFLEN];
+ buf[utf_char2bytes(code, buf)] = NUL;
+ rettv->vval.v_string = xstrdup(buf);
}
/// "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;
@@ -2010,8 +2010,8 @@ void f_digraph_setlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// structure used for b_kmap_ga.ga_data
typedef struct {
- char_u *from;
- char_u *to;
+ char *from;
+ char *to;
} kmap_T;
#define KMAP_MAXLEN 20 // maximum length of "from" or "to"
@@ -2064,10 +2064,10 @@ char *keymap_init(void)
/// @param eap
void ex_loadkeymap(exarg_T *eap)
{
- char_u *s;
+ char *s;
#define KMAP_LLEN 200 // max length of "to" and "from" together
- char_u buf[KMAP_LLEN + 11];
+ char buf[KMAP_LLEN + 11];
char *save_cpo = p_cpo;
if (!getline_equal(eap->getline, eap->cookie, getsourceline)) {
@@ -2092,15 +2092,15 @@ void ex_loadkeymap(exarg_T *eap)
break;
}
- char_u *p = (char_u *)skipwhite(line);
+ char *p = skipwhite(line);
if ((*p != '"') && (*p != NUL)) {
kmap_T *kp = GA_APPEND_VIA_PTR(kmap_T, &curbuf->b_kmap_ga);
s = skiptowhite(p);
- kp->from = vim_strnsave(p, (size_t)(s - p));
- p = (char_u *)skipwhite((char *)s);
+ kp->from = xstrnsave(p, (size_t)(s - p));
+ p = skipwhite(s);
s = skiptowhite(p);
- kp->to = vim_strnsave(p, (size_t)(s - p));
+ kp->to = xstrnsave(p, (size_t)(s - p));
if ((STRLEN(kp->from) + STRLEN(kp->to) >= KMAP_LLEN)
|| (*kp->from == NUL)
@@ -2118,10 +2118,10 @@ void ex_loadkeymap(exarg_T *eap)
// setup ":lmap" to map the keys
for (int i = 0; i < curbuf->b_kmap_ga.ga_len; i++) {
- vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s %s",
+ vim_snprintf(buf, sizeof(buf), "<buffer> %s %s",
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from,
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].to);
- (void)do_map(MAPTYPE_MAP, buf, MODE_LANGMAP, false);
+ (void)do_map(MAPTYPE_MAP, (char_u *)buf, MODE_LANGMAP, false);
}
p_cpo = save_cpo;
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 2b1b2607fb..fe23422bdc 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -11,9 +11,11 @@
#include "nvim/arabic.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/cursor_shape.h"
+#include "nvim/decoration.h"
#include "nvim/diff.h"
#include "nvim/drawline.h"
#include "nvim/fold.h"
@@ -116,7 +118,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 +143,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 +279,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
@@ -306,7 +308,7 @@ static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, SignText
if (row == startrow + filler_lines && filler_todo <= 0) {
SignTextAttrs *sattr = sign_get_attr(sign_idx, sattrs, wp->w_scwidth);
if (sattr != NULL) {
- *pp_extra = sattr->text;
+ *pp_extra = (char_u *)sattr->text;
if (*pp_extra != NULL) {
*c_extrap = NUL;
*c_finalp = NUL;
@@ -654,7 +656,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
has_decor = decor_redraw_line(buf, lnum - 1, &decor_state);
- providers_invoke_line(wp, providers, lnum - 1, &has_decor, provider_err);
+ decor_providers_invoke_line(wp, providers, lnum - 1, &has_decor, provider_err);
if (*provider_err) {
provider_err_virt_text(lnum, *provider_err);
@@ -687,7 +689,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Trick: skip a few chars for C/shell/Vim comments
nextline[SPWORDLEN] = NUL;
if (lnum < wp->w_buffer->b_ml.ml_line_count) {
- line = ml_get_buf(wp->w_buffer, lnum + 1, false);
+ line = (char_u *)ml_get_buf(wp->w_buffer, lnum + 1, false);
spell_cat_line(nextline + SPWORDLEN, line, SPWORDLEN);
}
@@ -864,13 +866,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
line_attr_lowprio_save = line_attr_lowprio;
}
- line = end_fill ? (char_u *)"" : ml_get_buf(wp->w_buffer, lnum, false);
+ line = end_fill ? (char_u *)"" : (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
ptr = line;
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 +942,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, (char *)line, (char *)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 +972,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);
}
}
@@ -997,7 +1006,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
len = spell_move_to(wp, FORWARD, true, true, &spell_hlf);
// spell_move_to() may call ml_get() and make "line" invalid
- line = ml_get_buf(wp->w_buffer, lnum, false);
+ line = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
ptr = line + linecol;
if (len == 0 || (int)wp->w_cursor.col > ptr - line) {
@@ -1164,7 +1173,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;
@@ -1215,7 +1224,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
c_extra = ' ';
c_final = NUL;
n_extra =
- get_breakindent_win(wp, ml_get_buf(wp->w_buffer, lnum, false));
+ get_breakindent_win(wp, (char_u *)ml_get_buf(wp->w_buffer, lnum, false));
if (row == startrow) {
n_extra -= win_col_off2(wp);
if (n_extra < 0) {
@@ -1247,7 +1256,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;
@@ -1342,7 +1351,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
linenr_T lnume = lnum + foldinfo.fi_lines - 1;
memset(buf_fold, ' ', FOLD_TEXT_LEN);
- p_extra = get_foldtext(wp, lnum, lnume, foldinfo, buf_fold);
+ p_extra = (char_u *)get_foldtext(wp, lnum, lnume, foldinfo, (char *)buf_fold);
n_extra = (int)STRLEN(p_extra);
if (p_extra != buf_fold) {
@@ -1482,7 +1491,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 +1542,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 +1600,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];
}
@@ -1639,7 +1648,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
ptr++;
if (extra_check) {
- bool can_spell = true;
+ bool no_plain_buffer = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) != 0;
+ bool can_spell = !no_plain_buffer;
// Get syntax attribute, unless still at the start of the line
// (double-wide char that doesn't fit).
@@ -1666,7 +1676,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Need to get the line again, a multi-line regexp may
// have made it invalid.
- line = ml_get_buf(wp->w_buffer, lnum, false);
+ line = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
ptr = line + v;
if (!attr_pri) {
@@ -1691,6 +1701,29 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
char_attr = 0;
}
+ if (has_decor && v > 0) {
+ bool selected = (area_active || (area_highlighting && noinvcur
+ && (colnr_T)vcol == wp->w_virtcol));
+ int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, off,
+ selected, &decor_state);
+ if (extmark_attr != 0) {
+ if (!attr_pri) {
+ char_attr = hl_combine_attr(char_attr, extmark_attr);
+ } else {
+ char_attr = hl_combine_attr(extmark_attr, char_attr);
+ }
+ }
+
+ decor_conceal = decor_state.conceal;
+ if (decor_conceal && decor_state.conceal_char) {
+ decor_conceal = 2; // really??
+ }
+
+ if (decor_state.spell) {
+ can_spell = true;
+ }
+ }
+
// Check spelling (unless at the end of the line).
// Only do this when there is no syntax highlighting, the
// @Spell cluster is not used or the current syntax item
@@ -1699,9 +1732,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (has_spell && v >= word_end && v > cur_checked_col) {
spell_attr = 0;
if (!attr_pri) {
- char_attr = syntax_attr;
+ char_attr = hl_combine_attr(char_attr, syntax_attr);
}
- if (c != 0 && (!has_syntax || can_spell)) {
+ if (c != 0 && ((!has_syntax && !no_plain_buffer) || can_spell)) {
char_u *prev_ptr;
char_u *p;
int len;
@@ -1774,32 +1807,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
char_attr = hl_combine_attr(term_attrs[vcol], char_attr);
}
- if (has_decor && v > 0) {
- bool selected = (area_active || (area_highlighting && noinvcur
- && (colnr_T)vcol == wp->w_virtcol));
- int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, off,
- selected, &decor_state);
- if (extmark_attr != 0) {
- if (!attr_pri) {
- char_attr = hl_combine_attr(char_attr, extmark_attr);
- } else {
- char_attr = hl_combine_attr(extmark_attr, char_attr);
- }
- }
-
- decor_conceal = decor_state.conceal;
- if (decor_conceal && decor_state.conceal_char) {
- decor_conceal = 2; // really??
- }
- }
-
// Found last space before word: check for line break.
if (wp->w_p_lbr && c0 == c && vim_isbreak(c)
&& !vim_isbreak((int)(*ptr))) {
- int mb_off = utf_head_off(line, ptr - 1);
+ int mb_off = utf_head_off((char *)line, (char *)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, (char *)line, (char *)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 +1841,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 +2099,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)
@@ -2334,6 +2351,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
col_attr = cuc_attr;
} else if (draw_color_col && VCOL_HLC == *color_cols) {
col_attr = mc_attr;
+ c = wp->w_p_fcs_chars.colorcol;
+ schar_from_char(linebuf_char[off], c);
}
col_attr = hl_combine_attr(col_attr, line_attr);
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index 2abff6c894..8df4e5047d 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,14 +532,14 @@ 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);
}
ui_comp_set_screen_valid(true);
DecorProviders providers;
- decor_providers_start(&providers, type, &provider_err);
+ decor_providers_start(&providers, &provider_err);
// "start" callback could have changed highlights for global elements
if (win_check_ns_hl(NULL)) {
@@ -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);
}
@@ -694,13 +696,61 @@ static void win_redr_border(win_T *wp)
int *adj = wp->w_border_adj;
int irow = wp->w_height_inner + wp->w_winbar_height, icol = wp->w_width_inner;
+ char* title = wp->w_float_config.title;
+ size_t n_title = wp->w_float_config.n_title;
+ stl_hlrec_t* title_hl = wp->w_float_config.title_hl;
+
+ int m8[MAX_MCO + 1];
+ int cc;
+ int len;
+ int t_attr = title_hl != NULL && title_hl->userhl
+ ? syn_id2attr(title_hl->userhl)
+ : 0;
+ t_attr = hl_combine_attr(attrs[1], t_attr);
+
+ int title_pos = 2;
+ switch (wp->w_float_config.title_pos) {
+ case kTitleLeft:
+ title_pos = 2;
+ break;
+ case kTitleRight:
+ title_pos = icol - 2 - vim_strsize(title);
+ break;
+ case kTitleCenter:
+ title_pos = (icol - vim_strsize(title)) / 2 - 1;
+ break;
+ }
+ title_pos = title_pos < 2 ? 2 : title_pos;
+
if (adj[0]) {
grid_puts_line_start(grid, 0);
if (adj[3]) {
grid_put_schar(grid, 0, 0, chars[0], attrs[0]);
}
for (int i = 0; i < icol; i++) {
- grid_put_schar(grid, 0, i + adj[3], chars[1], attrs[1]);
+ schar_T ch;
+ int attr;
+ // Draw the title if in the correct position.
+ if (i > title_pos && n_title > 0 && i < icol - 2) {
+ cc = utfc_ptr2char((char_u*) title, m8);
+ len = utfc_ptr2len(title);
+ n_title -= len;
+ title += len;
+
+ while (title_hl != NULL &&
+ (title_hl + 1)->start != NULL &&
+ (title_hl + 1)->start < title) {
+ ++ title_hl;
+ t_attr = hl_combine_attr(attrs[1], syn_id2attr(-title_hl->userhl));
+ }
+
+ schar_from_cc(ch, cc, m8);
+ attr = t_attr;
+ } else {
+ memcpy(ch, chars[1], sizeof(schar_T));
+ attr = attrs[1];
+ }
+ grid_put_schar(grid, 0, i + adj[3], ch, attr);
}
if (adj[1]) {
grid_put_schar(grid, 0, icol + adj[3], chars[2], attrs[2]);
@@ -746,6 +796,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 +814,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 +1010,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 +1069,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 +1100,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 +1112,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 +1226,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 +1237,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 +1250,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 +1392,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 +1940,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 +1973,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 +2039,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 +2069,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 +2110,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 +2124,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 +2140,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 +2160,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 +2170,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 +2219,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..1a8030d511 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1,9 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * edit.c: functions for Insert mode
- */
+// edit.c: functions for Insert mode
#include <assert.h>
#include <inttypes.h>
@@ -56,6 +54,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 +92,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 +108,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 +117,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
@@ -188,7 +188,7 @@ static void insert_enter(InsertState *s)
}
}
- Insstart_textlen = (colnr_T)linetabsize(get_cursor_line_ptr());
+ Insstart_textlen = (colnr_T)linetabsize((char_u *)get_cursor_line_ptr());
Insstart_blank_vcol = MAXCOL;
if (!did_ai) {
@@ -272,7 +272,7 @@ static void insert_enter(InsertState *s)
update_curswant();
if (((ins_at_eol && curwin->w_cursor.lnum == o_lnum)
|| curwin->w_curswant > curwin->w_virtcol)
- && *(s->ptr = get_cursor_line_ptr() + curwin->w_cursor.col) != NUL) {
+ && *(s->ptr = (char_u *)get_cursor_line_ptr() + curwin->w_cursor.col) != NUL) {
if (s->ptr[1] == NUL) {
curwin->w_cursor.col++;
} else {
@@ -448,7 +448,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 +624,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 +1091,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 +1177,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
}
@@ -1354,9 +1357,7 @@ void ins_redraw(bool ready)
emsg_on_display = false; // may remove error message now
}
-/*
- * Handle a CTRL-V or CTRL-Q typed in Insert mode.
- */
+// Handle a CTRL-V or CTRL-Q typed in Insert mode.
static void ins_ctrl_v(void)
{
int c;
@@ -1386,10 +1387,8 @@ static void ins_ctrl_v(void)
revins_legal++;
}
-/*
- * Put a character directly onto the screen. It's not stored in a buffer.
- * Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
- */
+// Put a character directly onto the screen. It's not stored in a buffer.
+// Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
static int pc_status;
#define PC_STATUS_UNSET 0 // pc_bytes was not set
#define PC_STATUS_RIGHT 1 // right half of double-wide char
@@ -1440,21 +1439,21 @@ void edit_putchar(int c, bool highlight)
}
}
-/// Return the effective prompt for the specified buffer.
-char_u *buf_prompt_text(const buf_T *const buf)
+/// @return the effective prompt for the specified buffer.
+char *buf_prompt_text(const buf_T *const buf)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
if (buf->b_prompt_text == NULL) {
- return (char_u *)"% ";
+ return "% ";
}
- return (char_u *)buf->b_prompt_text;
+ return buf->b_prompt_text;
}
// Return the effective prompt for the current buffer.
char_u *prompt_text(void)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
- return buf_prompt_text(curbuf);
+ return (char_u *)buf_prompt_text(curbuf);
}
// Prepare for prompt mode: Make sure the last line has the prompt text.
@@ -1465,7 +1464,7 @@ static void init_prompt(int cmdchar_todo)
char_u *text;
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- text = get_cursor_line_ptr();
+ text = (char_u *)get_cursor_line_ptr();
if (STRNCMP(text, prompt, STRLEN(prompt)) != 0) {
// prompt is missing, insert it or append a line with it
if (*text == NUL) {
@@ -1506,9 +1505,7 @@ bool prompt_curpos_editable(void)
&& curwin->w_cursor.col >= (int)STRLEN(prompt_text());
}
-/*
- * Undo the previous edit_putchar().
- */
+// Undo the previous edit_putchar().
void edit_unputchar(void)
{
if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled) {
@@ -1518,16 +1515,13 @@ 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);
}
}
}
-/*
- * Called when p_dollar is set: display a '$' at the end of the changed text
- * Only works when cursor is in the line that changes.
- */
+// Called when p_dollar is set: display a '$' at the end of the changed text
+// Only works when cursor is in the line that changes.
void display_dollar(colnr_T col)
{
colnr_T save_col;
@@ -1540,8 +1534,8 @@ void display_dollar(colnr_T col)
curwin->w_cursor.col = col;
// If on the last byte of a multi-byte move to the first byte.
- char_u *p = get_cursor_line_ptr();
- curwin->w_cursor.col -= utf_head_off(p, p + col);
+ char_u *p = (char_u *)get_cursor_line_ptr();
+ curwin->w_cursor.col -= utf_head_off((char *)p, (char *)p + col);
curs_columns(curwin, false); // Recompute w_wrow and w_wcol
if (curwin->w_wcol < curwin->w_grid.cols) {
edit_putchar('$', false);
@@ -1550,11 +1544,9 @@ void display_dollar(colnr_T col)
curwin->w_cursor.col = save_col;
}
-/*
- * Call this function before moving the cursor from the normal insert position
- * in insert mode.
- */
-static void undisplay_dollar(void)
+// Call this function before moving the cursor from the normal insert position
+// in insert mode.
+void undisplay_dollar(void)
{
if (dollar_vcol >= 0) {
dollar_vcol = -1;
@@ -1568,7 +1560,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)
@@ -1582,25 +1574,23 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
int start_col;
colnr_T vc;
colnr_T orig_col = 0; // init for GCC
- char_u *new_line, *orig_line = NULL; // init for GCC
+ char *new_line, *orig_line = NULL; // init for GCC
// MODE_VREPLACE state needs to know what the line was like before changing
if (State & VREPLACE_FLAG) {
- orig_line = vim_strsave(get_cursor_line_ptr()); // Deal with NULL below
+ orig_line = xstrdup(get_cursor_line_ptr()); // Deal with NULL below
orig_col = curwin->w_cursor.col;
}
// 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;
- /*
- * For Replace mode we need to fix the replace stack later, which is only
- * possible when the cursor is in the indent. Remember the number of
- * characters before the cursor if it's possible.
- */
+ // For Replace mode we need to fix the replace stack later, which is only
+ // possible when the cursor is in the indent. Remember the number of
+ // characters before the cursor if it's possible.
start_col = curwin->w_cursor.col;
// determine offset from first non-blank
@@ -1610,10 +1600,8 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
insstart_less = curwin->w_cursor.col;
- /*
- * If the cursor is in the indent, compute how many screen columns the
- * cursor is to the left of the first non-blank.
- */
+ // If the cursor is in the indent, compute how many screen columns the
+ // cursor is to the left of the first non-blank.
if (new_cursor_col < 0) {
vcol = get_indent() - vcol;
}
@@ -1622,9 +1610,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
start_col = -1;
}
- /*
- * Set the new indent. The cursor will be put on the first non-blank.
- */
+ // Set the new indent. The cursor will be put on the first non-blank.
if (type == INDENT_SET) {
(void)set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0);
} else {
@@ -1639,20 +1625,16 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
}
insstart_less -= curwin->w_cursor.col;
- /*
- * Try to put cursor on same character.
- * If the cursor is at or after the first non-blank in the line,
- * compute the cursor column relative to the column of the first
- * non-blank character.
- * If we are not in insert mode, leave the cursor on the first non-blank.
- * If the cursor is before the first non-blank, position it relative
- * to the first non-blank, counted in screen columns.
- */
+ // Try to put cursor on same character.
+ // If the cursor is at or after the first non-blank in the line,
+ // compute the cursor column relative to the column of the first
+ // non-blank character.
+ // If we are not in insert mode, leave the cursor on the first non-blank.
+ // If the cursor is before the first non-blank, position it relative
+ // to the first non-blank, counted in screen columns.
if (new_cursor_col >= 0) {
- /*
- * When changing the indent while the cursor is touching it, reset
- * Insstart_col to 0.
- */
+ // When changing the indent while the cursor is touching it, reset
+ // Insstart_col to 0.
if (new_cursor_col == 0) {
insstart_less = MAXCOL;
}
@@ -1660,47 +1642,43 @@ 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;
- 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++;
+ // Advance the cursor until we reach the right screen column.
+ last_vcol = 0;
+ ptr = (char_u *)get_cursor_line_ptr();
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin, 0, 0, (char *)ptr, (char *)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);
}
- vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol);
+ if (*cts.cts_ptr == NUL) {
+ break;
+ }
+ 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
- * the right screen column.
- */
+ // May need to insert spaces to be able to position the cursor on
+ // the right screen column.
if (vcol != (int)curwin->w_virtcol) {
curwin->w_cursor.col = (colnr_T)new_cursor_col;
size_t i = (size_t)(curwin->w_virtcol - vcol);
ptr = xmallocz(i);
memset(ptr, ' ', i);
new_cursor_col += (int)i;
- ins_str(ptr);
+ ins_str((char *)ptr);
xfree(ptr);
}
- /*
- * When changing the indent while the cursor is in it, reset
- * Insstart_col to 0.
- */
+ // When changing the indent while the cursor is in it, reset
+ // Insstart_col to 0.
insstart_less = MAXCOL;
}
@@ -1711,12 +1689,10 @@ 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();
- /*
- * May have to adjust the start of the insert.
- */
+ // May have to adjust the start of the insert.
if (State & MODE_INSERT) {
if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0) {
if ((int)Insstart.col <= insstart_less) {
@@ -1757,14 +1733,14 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
// then put it back again the way we wanted it.
if (State & VREPLACE_FLAG) {
// Save new line
- new_line = vim_strsave(get_cursor_line_ptr());
+ new_line = xstrdup(get_cursor_line_ptr());
// We only put back the new line up to the cursor
new_line[curwin->w_cursor.col] = NUL;
int new_col = curwin->w_cursor.col;
// Put back original line
- ml_replace(curwin->w_cursor.lnum, (char *)orig_line, false);
+ ml_replace(curwin->w_cursor.lnum, orig_line, false);
curwin->w_cursor.col = orig_col;
curbuf_splice_pending++;
@@ -1792,7 +1768,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;
@@ -1837,7 +1813,7 @@ static bool del_char_after_col(int limit_col)
// composing character.
mb_adjust_cursor();
while (curwin->w_cursor.col < (colnr_T)limit_col) {
- int l = utf_ptr2len((char *)get_cursor_pos_ptr());
+ int l = utf_ptr2len(get_cursor_pos_ptr());
if (l == 0) { // end of line
break;
@@ -1971,7 +1947,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 +1960,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;
}
@@ -1994,20 +1970,15 @@ static void insert_special(int c, int allow_modmask, int ctrlv)
}
}
-/*
- * Special characters in this context are those that need processing other
- * than the simple insertion that can be performed here. This includes ESC
- * which terminates the insert, and CR/NL which need special processing to
- * open up a new line. This routine tries to optimize insertions performed by
- * the "redo", "undo" or "put" commands, so it needs to know when it should
- * stop and defer processing to the "normal" mechanism.
- * '0' and '^' are special, because they can be followed by CTRL-D.
- */
+// Special characters in this context are those that need processing other
+// than the simple insertion that can be performed here. This includes ESC
+// which terminates the insert, and CR/NL which need special processing to
+// open up a new line. This routine tries to optimize insertions performed by
+// the "redo", "undo" or "put" commands, so it needs to know when it should
+// stop and defer processing to the "normal" mechanism.
+// '0' and '^' are special, because they can be followed by CTRL-D.
#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
@@ -2081,7 +2052,7 @@ void insertchar(int c, int flags, int second_indent)
// Need to remove existing (middle) comment leader and insert end
// comment leader. First, check what comment leader we can find.
- char_u *line = get_cursor_line_ptr();
+ char_u *line = (char_u *)get_cursor_line_ptr();
int i = get_leader_len((char *)line, &p, false, true);
if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL) { // Just checking
// Skip middle-comment string
@@ -2115,7 +2086,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 +2146,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 +2164,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,600 +2177,7 @@ 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.
- */
+// Put a character in the redo buffer, for when just after a CTRL-V.
static void redo_literal(int c)
{
char buf[10];
@@ -2849,10 +2227,8 @@ static void start_arrow_common(pos_T *end_insert_pos, bool end_change)
check_spell_redraw();
}
-/*
- * If we skipped highlighting word at cursor, do it now.
- * It may be skipped again, thus reset spell_redraw_lnum first.
- */
+// If we skipped highlighting word at cursor, do it now.
+// It may be skipped again, thus reset spell_redraw_lnum first.
static void check_spell_redraw(void)
{
if (spell_redraw_lnum != 0) {
@@ -2863,11 +2239,9 @@ static void check_spell_redraw(void)
}
}
-/*
- * stop_arrow() is called before a change is made in insert mode.
- * If an arrow key has been used, start a new insertion.
- * Returns FAIL if undo is impossible, shouldn't insert then.
- */
+// stop_arrow() is called before a change is made in insert mode.
+// If an arrow key has been used, start a new insertion.
+// Returns FAIL if undo is impossible, shouldn't insert then.
int stop_arrow(void)
{
if (arrow_used) {
@@ -2877,7 +2251,7 @@ int stop_arrow(void)
// right, except when nothing was inserted yet.
update_Insstart_orig = false;
}
- Insstart_textlen = (colnr_T)linetabsize(get_cursor_line_ptr());
+ Insstart_textlen = (colnr_T)linetabsize((char_u *)get_cursor_line_ptr());
if (u_save_cursor() == OK) {
arrow_used = false;
@@ -2917,11 +2291,9 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
stop_redo_ins();
replace_flush(); // abandon replace stack
- /*
- * Save the inserted text for later redo with ^@ and CTRL-A.
- * Don't do it when "restart_edit" was set and nothing was inserted,
- * otherwise CTRL-O w and then <Left> will clear "last_insert".
- */
+ // Save the inserted text for later redo with ^@ and CTRL-A.
+ // Don't do it when "restart_edit" was set and nothing was inserted,
+ // otherwise CTRL-O w and then <Left> will clear "last_insert".
ptr = get_inserted();
if (did_restart_edit == 0 || (ptr != NULL
&& (int)STRLEN(ptr) > new_insert_skip)) {
@@ -2958,8 +2330,8 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
if (gchar_cursor() != NUL) {
inc_cursor();
}
- /* If the cursor is still at the same character, also keep
- * the "coladd". */
+ // If the cursor is still at the same character, also keep
+ // the "coladd".
if (gchar_cursor() == NUL
&& curwin->w_cursor.lnum == tpos.lnum
&& curwin->w_cursor.col == tpos.col) {
@@ -2986,7 +2358,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 +2375,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
}
}
@@ -3028,10 +2400,8 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
}
}
-/*
- * Set the last inserted text to a single character.
- * Used for the replace command.
- */
+// Set the last inserted text to a single character.
+// Used for the replace command.
void set_last_insert(int c)
{
char_u *s;
@@ -3056,13 +2426,11 @@ void free_last_insert(void)
}
#endif
-/*
- * move cursor to start of line
- * if flags & BL_WHITE move to first non-white
- * if flags & BL_SOL move to first non-white if startofline is set,
- * otherwise keep "curswant" column
- * if flags & BL_FIX don't leave the cursor on a NUL.
- */
+// move cursor to start of line
+// if flags & BL_WHITE move to first non-white
+// if flags & BL_SOL move to first non-white if startofline is set,
+// otherwise keep "curswant" column
+// if flags & BL_FIX don't leave the cursor on a NUL.
void beginline(int flags)
{
if ((flags & BL_SOL) && !p_sol) {
@@ -3074,22 +2442,20 @@ void beginline(int flags)
if (flags & (BL_WHITE | BL_SOL)) {
char_u *ptr;
- for (ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr)
- && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr) {
- ++curwin->w_cursor.col;
+ for (ptr = (char_u *)get_cursor_line_ptr(); ascii_iswhite(*ptr)
+ && !((flags & BL_FIX) && ptr[1] == NUL); ptr++) {
+ curwin->w_cursor.col++;
}
}
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
}
}
-/*
- * oneright oneleft cursor_down cursor_up
- *
- * Move one char {right,left,down,up}.
- * Doesn't move onto the NUL past the end of the line, unless it is allowed.
- * Return OK when successful, FAIL when we hit a line of file boundary.
- */
+// oneright oneleft cursor_down cursor_up
+//
+// Move one char {right,left,down,up}.
+// Doesn't move onto the NUL past the end of the line, unless it is allowed.
+// Return OK when successful, FAIL when we hit a line of file boundary.
int oneright(void)
{
@@ -3100,7 +2466,7 @@ int oneright(void)
pos_T prevpos = curwin->w_cursor;
// Adjust for multi-wide char (excluding TAB)
- ptr = (char *)get_cursor_pos_ptr();
+ ptr = get_cursor_pos_ptr();
coladvance(getviscol() + ((*ptr != TAB && vim_isprintc(utf_ptr2char(ptr))) ?
ptr2cells(ptr) : 1));
curwin->w_set_curswant = true;
@@ -3109,7 +2475,7 @@ int oneright(void)
|| prevpos.coladd != curwin->w_cursor.coladd) ? OK : FAIL;
}
- ptr = (char *)get_cursor_pos_ptr();
+ ptr = get_cursor_pos_ptr();
if (*ptr == NUL) {
return FAIL; // already at the very end
}
@@ -3123,7 +2489,7 @@ int oneright(void)
}
curwin->w_cursor.col += l;
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
return OK;
}
@@ -3152,13 +2518,13 @@ int oneleft(void)
if (curwin->w_cursor.coladd == 1) {
// Adjust for multi-wide char (not a TAB)
- char *ptr = (char *)get_cursor_pos_ptr();
+ char *ptr = get_cursor_pos_ptr();
if (*ptr != TAB && vim_isprintc(utf_ptr2char(ptr)) && ptr2cells(ptr) > 1) {
curwin->w_cursor.coladd = 0;
}
}
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
return OK;
}
@@ -3166,8 +2532,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 +2541,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;
@@ -3190,9 +2556,8 @@ int cursor_up(long n, int upd_topline)
if (n >= lnum) {
lnum = 1;
} else if (hasAnyFolding(curwin)) {
- /*
- * Count each sequence of folded lines as one logical line.
- */
+ // Count each sequence of folded lines as one logical line.
+
// go to the start of the current fold
(void)hasFolding(lnum, &lnum, NULL);
@@ -3230,7 +2595,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 +2653,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 +2668,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;
}
@@ -3351,25 +2716,23 @@ char_u *get_last_insert(void)
return last_insert + last_insert_skip;
}
-/*
- * Get last inserted string, and remove trailing <Esc>.
- * Returns pointer to allocated memory (must be freed) or NULL.
- */
+// Get last inserted string, and remove trailing <Esc>.
+// Returns pointer to allocated memory (must be freed) or NULL.
char_u *get_last_insert_save(void)
{
- char_u *s;
+ char *s;
int len;
if (last_insert == NULL) {
return NULL;
}
- s = vim_strsave(last_insert + last_insert_skip);
+ s = xstrdup((char *)last_insert + last_insert_skip);
len = (int)STRLEN(s);
if (len > 0 && s[len - 1] == ESC) { // remove trailing ESC
s[len - 1] = NUL;
}
- return s;
+ return (char_u *)s;
}
/// Check the word in front of the cursor for an abbreviation.
@@ -3389,24 +2752,22 @@ static bool echeck_abbr(int c)
return false;
}
- return check_abbr(c, get_cursor_line_ptr(), curwin->w_cursor.col,
+ return check_abbr(c, (char_u *)get_cursor_line_ptr(), curwin->w_cursor.col,
curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0);
}
-/*
- * replace-stack functions
- *
- * When replacing characters, the replaced characters are remembered for each
- * new character. This is used to re-insert the old text when backspacing.
- *
- * There is a NUL headed list of characters for each character that is
- * currently in the file after the insertion point. When BS is used, one NUL
- * headed list is put back for the deleted character.
- *
- * For a newline, there are two NUL headed lists. One contains the characters
- * that the NL replaced. The extra one stores the characters after the cursor
- * that were deleted (always white space).
- */
+// replace-stack functions
+//
+// When replacing characters, the replaced characters are remembered for each
+// new character. This is used to re-insert the old text when backspacing.
+//
+// There is a NUL headed list of characters for each character that is
+// currently in the file after the insertion point. When BS is used, one NUL
+// headed list is put back for the deleted character.
+//
+// For a newline, there are two NUL headed lists. One contains the characters
+// that the NL replaced. The extra one stores the characters after the cursor
+// that were deleted (always white space).
static char_u *replace_stack = NULL;
static ssize_t replace_stack_nr = 0; // next entry in replace stack
@@ -3437,17 +2798,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;
@@ -3492,10 +2852,8 @@ static void replace_pop_ins(void)
State = oldState;
}
-/*
- * Insert bytes popped from the replace stack. "cc" is the first byte. If it
- * indicates a multi-byte char, pop the other bytes too.
- */
+// Insert bytes popped from the replace stack. "cc" is the first byte. If it
+// indicates a multi-byte char, pop the other bytes too.
static void mb_replace_pop_ins(int cc)
{
int n;
@@ -3508,7 +2866,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 +2889,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--) {
@@ -3542,10 +2900,8 @@ static void mb_replace_pop_ins(int cc)
}
}
-/*
- * make the replace stack empty
- * (called when exiting replace mode)
- */
+// make the replace stack empty
+// (called when exiting replace mode)
static void replace_flush(void)
{
XFREE_CLEAR(replace_stack);
@@ -3553,15 +2909,13 @@ static void replace_flush(void)
replace_stack_nr = 0;
}
-/*
- * Handle doing a BS for one character.
- * cc < 0: replace stack empty, just move cursor
- * cc == 0: character was inserted, delete it
- * cc > 0: character was replaced, put cc (first byte of original char) back
- * and check for more characters to be put back
- * When "limit_col" is >= 0, don't delete before this column. Matters when
- * using composing characters, use del_char_after_col() instead of del_char().
- */
+// Handle doing a BS for one character.
+// cc < 0: replace stack empty, just move cursor
+// cc == 0: character was inserted, delete it
+// cc > 0: character was replaced, put cc (first byte of original char) back
+// and check for more characters to be put back
+// When "limit_col" is >= 0, don't delete before this column. Matters when
+// using composing characters, use del_char_after_col() instead of del_char().
static void replace_do_bs(int limit_col)
{
int cc;
@@ -3591,11 +2945,11 @@ static void replace_do_bs(int limit_col)
if (l_State & VREPLACE_FLAG) {
// Get the number of screen cells used by the inserted characters
- p = get_cursor_pos_ptr();
+ p = (char_u *)get_cursor_pos_ptr();
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;
@@ -3624,12 +2978,10 @@ bool cindent_on(void)
return !p_paste && (curbuf->b_p_cin || *curbuf->b_p_inde != NUL);
}
-/*
- * Re-indent the current line, based on the current contents of it and the
- * surrounding lines. Fixing the cursor position seems really easy -- I'm very
- * confused what all the part that handles Control-T is doing that I'm not.
- * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
- */
+// Re-indent the current line, based on the current contents of it and the
+// surrounding lines. Fixing the cursor position seems really easy -- I'm very
+// confused what all the part that handles Control-T is doing that I'm not.
+// "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
void fixthisline(IndentGetter get_the_indent)
{
int amount = get_the_indent();
@@ -3657,7 +3009,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,22 +3034,20 @@ 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) {
- /*
- * Find out if we want to try a match with this key, depending on
- * 'when' and a '*' or '!' before the key.
- */
+ // Find out if we want to try a match with this key, depending on
+ // 'when' and a '*' or '!' before the key.
switch (when) {
case '*':
try_match = (*look == '*'); break;
case '!':
try_match = (*look == '!'); break;
default:
- try_match = (*look != '*'); break;
+ try_match = (*look != '*') && (*look != '!'); break;
}
if (*look == '*' || *look == '!') {
look++;
@@ -3739,7 +3089,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
// cursor.
} else if (*look == 'e') {
if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4) {
- p = get_cursor_line_ptr();
+ p = (char_u *)get_cursor_line_ptr();
if ((char_u *)skipwhite((char *)p) == p + curwin->w_cursor.col - 4
&& STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0) {
return true;
@@ -3752,12 +3102,12 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
// class::method for C++).
} else if (*look == ':') {
if (try_match && keytyped == ':') {
- p = get_cursor_line_ptr();
+ p = (char_u *)get_cursor_line_ptr();
if (cin_iscase(p, false) || cin_isscopedecl(p) || cin_islabel()) {
return true;
}
// Need to get the line again after cin_islabel().
- p = get_cursor_line_ptr();
+ p = (char_u *)get_cursor_line_ptr();
if (curwin->w_cursor.col > 2
&& p[curwin->w_cursor.col - 1] == ':'
&& p[curwin->w_cursor.col - 2] == ':') {
@@ -3765,7 +3115,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
const bool i = cin_iscase(p, false)
|| cin_isscopedecl(p)
|| cin_islabel();
- p = get_cursor_line_ptr();
+ p = (char_u *)get_cursor_line_ptr();
p[curwin->w_cursor.col - 1] = ':';
if (i) {
return true;
@@ -3815,9 +3165,9 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
if (keytyped == KEY_COMPLETE) {
char_u *n, *s;
- /* Just completed a word, check if it starts with "look".
- * search back for the start of a word. */
- line = get_cursor_line_ptr();
+ // Just completed a word, check if it starts with "look".
+ // search back for the start of a word.
+ line = (char_u *)get_cursor_line_ptr();
for (s = line + curwin->w_cursor.col; s > line; s = n) {
n = mb_prevptr(line, s);
if (!vim_iswordp(n)) {
@@ -3827,7 +3177,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
assert(p >= look && (uintmax_t)(p - look) <= SIZE_MAX);
if (s + (p - look) <= line + curwin->w_cursor.col
&& (icase
- ? mb_strnicmp(s, look, (size_t)(p - look))
+ ? mb_strnicmp((char *)s, (char *)look, (size_t)(p - look))
: STRNCMP(s, look, p - look)) == 0) {
match = true;
}
@@ -3836,20 +3186,20 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
if (keytyped == (int)p[-1]
|| (icase && keytyped < 256
&& TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1]))) {
- line = get_cursor_pos_ptr();
+ line = (char_u *)get_cursor_pos_ptr();
assert(p >= look && (uintmax_t)(p - look) <= SIZE_MAX);
if ((curwin->w_cursor.col == (colnr_T)(p - look)
|| !vim_iswordc(line[-(p - look) - 1]))
&& (icase
- ? mb_strnicmp(line - (p - look), look, (size_t)(p - look))
+ ? mb_strnicmp((char *)line - (p - look), (char *)look, (size_t)(p - look))
: STRNCMP(line - (p - look), look, p - look)) == 0) {
match = true;
}
}
}
if (match && try_match_word && !try_match) {
- /* "0=word": Check if there are only blanks before the
- * word. */
+ // "0=word": Check if there are only blanks before the
+ // word.
if (getwhitecols_curline() !=
(int)(curwin->w_cursor.col - (p - look))) {
match = false;
@@ -3871,17 +3221,13 @@ 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;
}
-/*
- * Map Hebrew keyboard when in hkmap mode.
- */
+// Map Hebrew keyboard when in hkmap mode.
int hkmap(int c)
FUNC_ATTR_PURE
{
@@ -3983,9 +3329,7 @@ static void ins_reg(void)
int literally = 0;
int vis_active = VIsual_active;
- /*
- * If we are going to wait for a character, show a '"'.
- */
+ // If we are going to wait for a character, show a '"'.
pc_status = PC_STATUS_UNSET;
if (redrawing() && !char_avail()) {
// may need to redraw when no more chars available now
@@ -4000,13 +3344,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 +3388,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;
}
@@ -4067,9 +3411,7 @@ static void ins_reg(void)
}
}
-/*
- * CTRL-G commands in Insert mode.
- */
+// CTRL-G commands in Insert mode.
static void ins_ctrl_g(void)
{
int c;
@@ -4123,9 +3465,7 @@ static void ins_ctrl_g(void)
}
}
-/*
- * CTRL-^ in Insert mode.
- */
+// CTRL-^ in Insert mode.
static void ins_ctrl_hat(void)
{
if (map_to_exists_mode("", MODE_LANGMAP, false)) {
@@ -4169,10 +3509,8 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
AppendToRedobuff(ESC_STR);
}
- /*
- * Repeating insert may take a long time. Check for
- * interrupt now and then.
- */
+ // Repeating insert may take a long time. Check for
+ // interrupt now and then.
if (*count > 0) {
line_breakcheck();
if (got_int) {
@@ -4195,7 +3533,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();
}
@@ -4215,10 +3553,8 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
RESET_FMARK(&curbuf->b_last_insert, curwin->w_cursor, curbuf->b_fnum, view);
}
- /*
- * The cursor should end up on the last inserted character.
- * Don't do it for CTRL-O, unless past the end of the line.
- */
+ // The cursor should end up on the last inserted character.
+ // Don't do it for CTRL-O, unless past the end of the line.
if (!nomove
&& (curwin->w_cursor.col != 0 || curwin->w_cursor.coladd > 0)
&& (restart_edit == NUL || (gchar_cursor() == NUL && !VIsual_active))
@@ -4256,15 +3592,13 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
return true;
}
-/*
- * Toggle language: hkmap and revins_on.
- * Move to end of reverse inserted text.
- */
+// Toggle language: hkmap and revins_on.
+// Move to end of reverse inserted text.
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;
@@ -4326,9 +3660,7 @@ static bool ins_start_select(int c)
return false;
}
-/*
- * <Insert> key in Insert mode: toggle insert/replace mode.
- */
+// <Insert> key in Insert mode: toggle insert/replace mode.
static void ins_insert(int replaceState)
{
set_vim_var_string(VV_INSERTMODE, ((State & REPLACE_FLAG) ? "i" :
@@ -4346,9 +3678,7 @@ static void ins_insert(int replaceState)
ui_cursor_shape(); // may show different cursor shape
}
-/*
- * Pressed CTRL-O in Insert mode.
- */
+// Pressed CTRL-O in Insert mode.
static void ins_ctrl_o(void)
{
if (State & VREPLACE_FLAG) {
@@ -4365,13 +3695,11 @@ static void ins_ctrl_o(void)
}
}
-/*
- * If the cursor is on an indent, ^T/^D insert/delete one
- * shiftwidth. Otherwise ^T/^D behave like a "<<" or ">>".
- * Always round the indent to 'shiftwidth', this is compatible
- * with vi. But vi only supports ^T and ^D after an
- * autoindent, we support it everywhere.
- */
+// If the cursor is on an indent, ^T/^D insert/delete one
+// shiftwidth. Otherwise ^T/^D behave like a "<<" or ">>".
+// Always round the indent to 'shiftwidth', this is compatible
+// with vi. But vi only supports ^T and ^D after an
+// autoindent, we support it everywhere.
static void ins_shift(int c, int lastc)
{
if (stop_arrow() == FAIL) {
@@ -4379,9 +3707,7 @@ static void ins_shift(int c, int lastc)
}
AppendCharToRedobuff(c);
- /*
- * 0^D and ^^D: remove all indent.
- */
+ // 0^D and ^^D: remove all indent.
if (c == Ctrl_D && (lastc == '0' || lastc == '^')
&& curwin->w_cursor.col > 0) {
curwin->w_cursor.col--;
@@ -4393,12 +3719,12 @@ 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) {
+ if (did_ai && *skipwhite(get_cursor_line_ptr()) != NUL) {
did_ai = false;
}
did_si = false;
@@ -4437,9 +3763,7 @@ static void ins_del(void)
AppendCharToRedobuff(K_DEL);
}
-/*
- * Delete one character for ins_bs().
- */
+// Delete one character for ins_bs().
static void ins_bs_one(colnr_T *vcolp)
{
dec_cursor();
@@ -4534,11 +3858,9 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
Insstart.lnum--;
Insstart.col = (colnr_T)STRLEN(ml_get(Insstart.lnum));
}
- /*
- * In replace mode:
- * cc < 0: NL was inserted, delete it
- * cc >= 0: NL was replaced, put original characters back
- */
+ // In replace mode:
+ // cc < 0: NL was inserted, delete it
+ // cc >= 0: NL was replaced, put original characters back
cc = -1;
if (State & REPLACE_FLAG) {
cc = replace_pop(); // returns -1 if NL was inserted
@@ -4558,7 +3880,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
// again when auto-formatting.
if (has_format_option(FO_AUTO)
&& has_format_option(FO_WHITE_PAR)) {
- char_u *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, true);
+ char_u *ptr = (char_u *)ml_get_buf(curbuf, curwin->w_cursor.lnum, true);
int len;
len = (int)STRLEN(ptr);
@@ -4567,7 +3889,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();
}
@@ -4618,9 +3940,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
curwin->w_cursor.col = save_col;
}
- /*
- * Handle deleting one 'shiftwidth' or 'softtabstop'.
- */
+ // Handle deleting one 'shiftwidth' or 'softtabstop'.
if (mode == BACKSPACE_CHAR
&& ((p_sta && in_indent)
|| ((get_sts_value() != 0
@@ -4654,7 +3974,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
// delete characters until we are at or before want_vcol
while (vcol > want_vcol && curwin->w_cursor.col > 0
- && (cc = *(get_cursor_pos_ptr() - 1), ascii_iswhite(cc))) {
+ && (cc = (uint8_t)(*(get_cursor_pos_ptr() - 1)), ascii_iswhite(cc))) {
ins_bs_one(&vcol);
}
@@ -4669,7 +3989,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);
}
@@ -4686,7 +4006,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
// Delete up to starting point, start of line or previous word.
int prev_cclass = 0;
- int cclass = mb_get_class(get_cursor_pos_ptr());
+ int cclass = mb_get_class((char_u *)get_cursor_pos_ptr());
do {
if (!revins_on) { // put cursor on char to be deleted
dec_cursor();
@@ -4694,7 +4014,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
cc = gchar_cursor();
// look multi-byte character class
prev_cclass = cclass;
- cclass = mb_get_class(get_cursor_pos_ptr());
+ cclass = mb_get_class((char_u *)get_cursor_pos_ptr());
if (mode == BACKSPACE_WORD && !ascii_isspace(cc)) { // start of word?
mode = BACKSPACE_WORD_NOT_SPACE;
temp = vim_iswordc(cc);
@@ -4849,7 +4169,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 +4200,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);
@@ -4966,14 +4286,14 @@ static void ins_right(void)
if (virtual_active()) {
oneright();
} else {
- curwin->w_cursor.col += utfc_ptr2len((char *)get_cursor_pos_ptr());
+ curwin->w_cursor.col += utfc_ptr2len(get_cursor_pos_ptr());
}
revins_legal++;
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 +4337,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 +4385,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,21 +4495,19 @@ 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);
}
}
}
- /*
- * When 'expandtab' not set: Replace spaces by TABs where possible.
- */
+ // When 'expandtab' not set: Replace spaces by TABs where possible.
if (!curbuf->b_p_et && (tabstop_count(curbuf->b_p_vsts_array) > 0
|| get_sts_value() > 0
|| (p_sta && ind))) {
char_u *ptr;
- char_u *saved_line = NULL; // init for GCC
+ char *saved_line = NULL; // init for GCC
pos_T pos;
pos_T fpos;
pos_T *cursor;
@@ -5202,10 +4520,10 @@ static bool ins_tab(void)
if (State & VREPLACE_FLAG) {
pos = curwin->w_cursor;
cursor = &pos;
- saved_line = vim_strsave(get_cursor_line_ptr());
- ptr = saved_line + pos.col;
+ saved_line = xstrdup(get_cursor_line_ptr());
+ ptr = (char_u *)saved_line + pos.col;
} else {
- ptr = get_cursor_pos_ptr();
+ ptr = (char_u *)get_cursor_pos_ptr();
cursor = &curwin->w_cursor;
}
@@ -5233,11 +4551,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, (char *)tab, (char *)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 +4574,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, (char *)ptr, (char *)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--;
@@ -5326,11 +4653,9 @@ bool ins_eol(int c)
}
undisplay_dollar();
- /*
- * Strange Vi behaviour: In Replace mode, typing a NL will not delete the
- * character under the cursor. Only push a NUL on the replace stack,
- * nothing to put back when the NL is deleted.
- */
+ // Strange Vi behaviour: In Replace mode, typing a NL will not delete the
+ // character under the cursor. Only push a NUL on the replace stack,
+ // nothing to put back when the NL is deleted.
if ((State & REPLACE_FLAG)
&& !(State & VREPLACE_FLAG)) {
replace_push(NUL);
@@ -5364,11 +4689,9 @@ bool ins_eol(int c)
return i;
}
-/*
- * Handle digraph in insert mode.
- * Returns character still to be inserted, or NUL when nothing remaining to be
- * done.
- */
+// Handle digraph in insert mode.
+// Returns character still to be inserted, or NUL when nothing remaining to be
+// done.
static int ins_digraph(void)
{
int c;
@@ -5400,7 +4723,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) {
@@ -5437,14 +4760,11 @@ static int ins_digraph(void)
return NUL;
}
-/*
- * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line.
- * Returns the char to be inserted, or NUL if none found.
- */
+// Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line.
+// Returns the char to be inserted, or NUL if none found.
int ins_copychar(linenr_T lnum)
{
int c;
- int temp;
char_u *ptr, *prev_ptr;
char_u *line;
@@ -5454,17 +4774,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 = (char_u *)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, (char *)line, (char *)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) {
@@ -5473,9 +4799,7 @@ int ins_copychar(linenr_T lnum)
return c;
}
-/*
- * CTRL-Y or CTRL-E typed in Insert mode.
- */
+// CTRL-Y or CTRL-E typed in Insert mode.
static int ins_ctrl_ey(int tc)
{
int c = tc;
@@ -5486,7 +4810,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 +4825,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++;
@@ -5512,10 +4836,8 @@ static int ins_ctrl_ey(int tc)
return c;
}
-/*
- * Try to do some very smart auto-indenting.
- * Used when inserting a "normal" character.
- */
+// Try to do some very smart auto-indenting.
+// Used when inserting a "normal" character.
static void ins_try_si(int c)
{
pos_T *pos, old_pos;
@@ -5523,21 +4845,17 @@ static void ins_try_si(int c)
int i;
bool temp;
- /*
- * do some very smart indenting when entering '{' or '}'
- */
+ // do some very smart indenting when entering '{' or '}'
if (((did_si || can_si_back) && c == '{') || (can_si && c == '}' && inindent(0))) {
// for '}' set indent equal to indent of line containing matching '{'
if (c == '}' && (pos = findmatch(NULL, '{')) != NULL) {
old_pos = curwin->w_cursor;
- /*
- * If the matching '{' has a ')' immediately before it (ignoring
- * white-space), then line up with the start of the line
- * containing the matching '(' if there is one. This handles the
- * case where an "if (..\n..) {" statement continues over multiple
- * lines -- webb
- */
- ptr = ml_get(pos->lnum);
+ // If the matching '{' has a ')' immediately before it (ignoring
+ // white-space), then line up with the start of the line
+ // containing the matching '(' if there is one. This handles the
+ // case where an "if (..\n..) {" statement continues over multiple
+ // lines -- webb
+ ptr = (char_u *)ml_get(pos->lnum);
i = pos->col;
if (i > 0) { // skip blanks before '{'
while (--i > 0 && ascii_iswhite(ptr[i])) {}
@@ -5550,7 +4868,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);
}
@@ -5562,7 +4880,7 @@ static void ins_try_si(int c)
old_pos = curwin->w_cursor;
i = get_indent();
while (curwin->w_cursor.lnum > 1) {
- ptr = (char_u *)skipwhite((char *)ml_get(--(curwin->w_cursor.lnum)));
+ ptr = (char_u *)skipwhite(ml_get(--(curwin->w_cursor.lnum)));
// ignore empty lines and lines starting with '#'.
if (*ptr != '#' && *ptr != NUL) {
@@ -5575,14 +4893,12 @@ 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);
}
}
}
- /*
- * set indent of '#' always to 0
- */
+ // set indent of '#' always to 0
if (curwin->w_cursor.col > 0 && can_si && c == '#' && inindent(0)) {
// remember current indent for next line
old_indent = get_indent();
@@ -5595,10 +4911,8 @@ static void ins_try_si(int c)
}
}
-/*
- * Get the value that w_virtcol would have when 'list' is off.
- * Unless 'cpo' contains the 'L' flag.
- */
+// Get the value that w_virtcol would have when 'list' is off.
+// Unless 'cpo' contains the 'L' flag.
colnr_T get_nolist_virtcol(void)
{
// check validity of cursor in current buffer
@@ -5613,12 +4927,10 @@ colnr_T get_nolist_virtcol(void)
return curwin->w_virtcol;
}
-/*
- * Handle the InsertCharPre autocommand.
- * "c" is the character that was typed.
- * Return a pointer to allocated memory with the replacement string.
- * Return NULL to continue inserting "c".
- */
+// Handle the InsertCharPre autocommand.
+// "c" is the character that was typed.
+// Return a pointer to allocated memory with the replacement string.
+// Return NULL to continue inserting "c".
static char_u *do_insert_char_pre(int c)
{
char buf[MB_MAXBYTES + 1];
@@ -5634,13 +4946,13 @@ static char_u *do_insert_char_pre(int c)
textlock++;
set_vim_var_string(VV_CHAR, buf, -1);
- char_u *res = NULL;
+ char *res = NULL;
if (ins_apply_autocmds(EVENT_INSERTCHARPRE)) {
// Get the value of v:char. It may be empty or more than one
// character. Only use it when changed, otherwise continue with the
// original character to avoid breaking autoindent.
- if (STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0) {
- res = vim_strsave((char_u *)get_vim_var_str(VV_CHAR));
+ if (strcmp(buf, get_vim_var_str(VV_CHAR)) != 0) {
+ res = xstrdup(get_vim_var_str(VV_CHAR));
}
}
@@ -5650,14 +4962,19 @@ static char_u *do_insert_char_pre(int c)
// Restore the State, it may have been changed.
State = save_State;
- return res;
+ return (char_u *)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 cb46e26f82..b65a17aeeb 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.
@@ -2297,7 +2292,7 @@ int eval0(char *arg, typval_T *rettv, char **nextcmd, int evaluate)
ret = FAIL;
}
if (nextcmd != NULL) {
- *nextcmd = (char *)check_nextcmd((char_u *)p);
+ *nextcmd = check_nextcmd(p);
}
return ret;
@@ -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;
@@ -3000,9 +2995,11 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
*arg = bp;
} else {
// decimal, hex or octal number
- vim_str2nr((char_u *)(*arg), NULL, &len, STR2NR_ALL, &n, NULL, 0, true);
+ vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true);
if (len == 0) {
- semsg(_(e_invexpr2), *arg);
+ if (evaluate) {
+ semsg(_(e_invexpr2), *arg);
+ }
ret = FAIL;
break;
}
@@ -3061,12 +3058,10 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
// Register contents: @r.
case '@':
(*arg)++;
+ int regname = mb_cptr2char_adv((const char_u**) arg);
if (evaluate) {
rettv->v_type = VAR_STRING;
- rettv->vval.v_string = get_reg_contents(**arg, kGRegExprSrc);
- }
- if (**arg != NUL) {
- (*arg)++;
+ rettv->vval.v_string = get_reg_contents(regname, kGRegExprSrc);
}
break;
@@ -3914,7 +3909,7 @@ char *partial_name(partial_T *pt)
FUNC_ATTR_PURE
{
if (pt->pt_name != NULL) {
- return (char *)pt->pt_name;
+ return pt->pt_name;
}
return (char *)pt->pt_func->uf_name;
}
@@ -3929,7 +3924,7 @@ static void partial_free(partial_T *pt)
xfree(pt->pt_argv);
tv_dict_unref(pt->pt_dict);
if (pt->pt_name != NULL) {
- func_unref(pt->pt_name);
+ func_unref((char_u *)pt->pt_name);
xfree(pt->pt_name);
} else {
func_ptr_unref(pt->pt_func);
@@ -4001,13 +3996,11 @@ failret:
bool func_equal(typval_T *tv1, typval_T *tv2, bool ic)
{
// empty and NULL function name considered the same
- char_u *s1 =
- (char_u *)(tv1->v_type == VAR_FUNC ? tv1->vval.v_string : partial_name(tv1->vval.v_partial));
+ char *s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string : partial_name(tv1->vval.v_partial);
if (s1 != NULL && *s1 == NUL) {
s1 = NULL;
}
- char_u *s2 =
- (char_u *)(tv2->v_type == VAR_FUNC ? tv2->vval.v_string : partial_name(tv2->vval.v_partial));
+ char *s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string : partial_name(tv2->vval.v_partial);
if (s2 != NULL && *s2 == NUL) {
s2 = NULL;
}
@@ -4015,7 +4008,7 @@ bool func_equal(typval_T *tv1, typval_T *tv2, bool ic)
if (s1 != s2) {
return false;
}
- } else if (STRCMP(s1, s2) != 0) {
+ } else if (strcmp(s1, s2) != 0) {
return false;
}
@@ -4166,7 +4159,7 @@ bool garbage_collect(bool testing)
// registers (ShaDa additional data)
{
- const void *reg_iter = NULL;
+ iter_register_T reg_iter = ITER_REGISTER_NULL;
do {
yankreg_T reg;
char name = NUL;
@@ -4175,7 +4168,7 @@ bool garbage_collect(bool testing)
if (name != NUL) {
ABORTING(set_ref_dict)(reg.additional_data, copyID);
}
- } while (reg_iter != NULL);
+ } while (reg_iter != ITER_REGISTER_NULL);
}
// global marks (ShaDa additional data)
@@ -4483,7 +4476,7 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack
// A partial does not have a copyID, because it cannot contain itself.
if (pt != NULL) {
- abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
+ abort = set_ref_in_func((char_u *)pt->pt_name, pt->pt_func, copyID);
if (pt->pt_dict != NULL) {
typval_T dtv;
@@ -4587,21 +4580,20 @@ static int dict_get_tv(char **arg, typval_T *rettv, int evaluate, bool literal)
{
typval_T tv;
char *key = NULL;
- char *start = skipwhite(*arg + 1);
+ char *curly_expr = skipwhite(*arg + 1);
char buf[NUMBUFLEN];
- // First check if it's not a curly-braces thing: {expr}.
+ // First check if it's not a curly-braces expression: {expr}.
// Must do this without evaluating, otherwise a function may be called
// twice. Unfortunately this means we need to call eval1() twice for the
// first item.
- // But {} is an empty Dictionary.
- if (*start != '}') {
- if (eval1(&start, &tv, false) == FAIL) { // recursive!
- return FAIL;
- }
- if (*skipwhite(start) == '}') {
- return NOTDONE;
- }
+ // "{}" is an empty Dictionary.
+ // "#{abc}" is never a curly-braces expression.
+ if (*curly_expr != '}'
+ && !literal
+ && eval1(&curly_expr, &tv, false) == OK
+ && *skipwhite(curly_expr) == '}') {
+ return NOTDONE;
}
dict_T *d = NULL;
@@ -4851,7 +4843,7 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
break;
}
- vimvars[VV_KEY].vv_str = (char *)vim_strsave(di->di_key);
+ vimvars[VV_KEY].vv_str = xstrdup((char *)di->di_key);
int r = filter_map_one(&di->di_tv, expr, map, &rem);
tv_clear(&vimvars[VV_KEY].vv_tv);
if (r == FAIL || did_emsg) {
@@ -4968,7 +4960,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;
@@ -5118,7 +5110,7 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref, FunPtr
func_ptr_ref(pt->pt_func);
xfree(name);
} else {
- pt->pt_name = (char_u *)name;
+ pt->pt_name = name;
func_ref((char_u *)name);
}
@@ -5228,12 +5220,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));
@@ -5863,13 +5855,8 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co
break;
case kCallbackLua:
- rv = nlua_call_ref(callback->data.luaref, NULL, args, true, NULL);
- switch (rv.type) {
- case kObjectTypeBoolean:
- return rv.data.boolean;
- default:
- return false;
- }
+ rv = nlua_call_ref(callback->data.luaref, NULL, args, false, NULL);
+ return (rv.type == kObjectTypeBoolean && rv.data.boolean == true);
case kCallbackNone:
return false;
@@ -5990,7 +5977,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();
}
}
@@ -6218,7 +6205,7 @@ char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl)
buf_T *buf = buflist_findnr((int)tv->vval.v_number);
if (buf) {
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
- for (char *p = (char *)ml_get_buf(buf, lnum, false); *p != NUL; p++) {
+ for (char *p = ml_get_buf(buf, lnum, false); *p != NUL; p++) {
*len += 1;
}
*len += 1;
@@ -6236,7 +6223,7 @@ char *save_tv_as_string(typval_T *tv, ptrdiff_t *const len, bool endnl)
char *ret = xmalloc((size_t)(*len) + 1);
char *end = ret;
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
- for (char *p = (char *)ml_get_buf(buf, lnum, false); *p != NUL; p++) {
+ for (char *p = ml_get_buf(buf, lnum, false); *p != NUL; p++) {
*end++ = (*p == '\n') ? NUL : *p;
}
*end++ = '\n';
@@ -6285,7 +6272,7 @@ int buf_byteidx_to_charidx(buf_T *buf, linenr_T lnum, int byteidx)
lnum = buf->b_ml.ml_line_count;
}
- char *str = (char *)ml_get_buf(buf, lnum, false);
+ char *str = ml_get_buf(buf, lnum, false);
if (*str == NUL) {
return 0;
@@ -6323,7 +6310,7 @@ int buf_charidx_to_byteidx(buf_T *buf, linenr_T lnum, int charidx)
lnum = buf->b_ml.ml_line_count;
}
- char *str = (char *)ml_get_buf(buf, lnum, false);
+ char *str = ml_get_buf(buf, lnum, false);
// Convert the character offset to a byte offset
char *t = str;
@@ -6374,7 +6361,7 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
}
int len;
if (charcol) {
- len = mb_charlen(ml_get(pos.lnum));
+ len = mb_charlen((char_u *)ml_get(pos.lnum));
} else {
len = (int)STRLEN(ml_get(pos.lnum));
}
@@ -6383,7 +6370,7 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
listitem_T *li = tv_list_find(l, 1L);
if (li != NULL && TV_LIST_ITEM_TV(li)->v_type == VAR_STRING
&& TV_LIST_ITEM_TV(li)->vval.v_string != NULL
- && STRCMP(TV_LIST_ITEM_TV(li)->vval.v_string, "$") == 0) {
+ && strcmp(TV_LIST_ITEM_TV(li)->vval.v_string, "$") == 0) {
pos.col = len + 1;
}
@@ -6421,7 +6408,7 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
}
} else if (name[0] == '\'') {
// mark
- int mname = (uint8_t)name[1];
+ int mname = utf_ptr2char(name + 1);
const fmark_T *const fm = mark_get(curbuf, curwin, NULL, kMarkAll, mname);
if (fm == NULL || fm->mark.lnum <= 0) {
return NULL;
@@ -6460,7 +6447,7 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
} else {
pos.lnum = curwin->w_cursor.lnum;
if (charcol) {
- pos.col = (colnr_T)mb_charlen(get_cursor_line_ptr());
+ pos.col = (colnr_T)mb_charlen((char_u *)get_cursor_line_ptr());
} else {
pos.col = (colnr_T)STRLEN(get_cursor_line_ptr());
}
@@ -6786,14 +6773,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)
{
@@ -6846,7 +6833,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) {
@@ -7405,7 +7392,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);
}
}
@@ -7532,9 +7519,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);
}
@@ -7644,7 +7631,7 @@ void ex_echo(exarg_T *eap)
tv_clear(&rettv);
arg = skipwhite(arg);
}
- eap->nextcmd = (char *)check_nextcmd((char_u *)arg);
+ eap->nextcmd = check_nextcmd(arg);
if (eap->skip) {
emsg_skip--;
@@ -7741,7 +7728,7 @@ void ex_execute(exarg_T *eap)
emsg_skip--;
}
- eap->nextcmd = (char *)check_nextcmd((char_u *)arg);
+ eap->nextcmd = check_nextcmd(arg);
}
/// Skip over the name of an option: "&option", "&g:option" or "&l:option".
@@ -7831,7 +7818,7 @@ bool script_autoload(const char *const name, const size_t name_len, const bool r
// "autoload/", it's always the same.
int i = 0;
for (; i < ga_loaded.ga_len; i++) {
- if (STRCMP(((char **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) {
+ if (strcmp(((char **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) {
break;
}
}
@@ -7985,7 +7972,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);
@@ -8082,7 +8069,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
@@ -8128,7 +8115,7 @@ repeat:
// Do not call shorten_fname() here since it removes the prefix
// even though the path does not have a prefix.
- if (FNAMENCMP(p, dirname, namelen) == 0) {
+ if (path_fnamencmp(p, dirname, namelen) == 0) {
p += namelen;
if (vim_ispathsep(*p)) {
while (*p && vim_ispathsep(*p)) {
@@ -8148,6 +8135,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;
@@ -8166,7 +8154,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);
}
@@ -8325,7 +8313,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);
@@ -8339,7 +8327,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags
while (vim_regexec_nl(&regmatch, (char_u *)str, (colnr_T)(tail - str))) {
// Skip empty match except for first match.
if (regmatch.startp[0] == regmatch.endp[0]) {
- if ((char_u *)zero_width == regmatch.startp[0]) {
+ if (zero_width == regmatch.startp[0]) {
// avoid getting stuck on a match with an empty string
int i = utfc_ptr2len(tail);
memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
@@ -8347,7 +8335,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags
tail += i;
continue;
}
- zero_width = (char *)regmatch.startp[0];
+ zero_width = regmatch.startp[0];
}
// Get some space for a temporary buffer to do the substitution
@@ -8360,14 +8348,14 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags
(regmatch.endp[0] - regmatch.startp[0])));
// copy the text up to where the match is
- int i = (int)(regmatch.startp[0] - (char_u *)tail);
+ int i = (int)(regmatch.startp[0] - tail);
memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
// add the substituted text
(void)vim_regsub(&regmatch, (char_u *)sub, expr,
(char_u *)ga.ga_data + ga.ga_len + i, sublen,
REGSUB_COPY | REGSUB_MAGIC);
ga.ga_len += i + sublen - 1;
- tail = (char *)regmatch.endp[0];
+ tail = regmatch.endp[0];
if (*tail == NUL) {
break;
}
@@ -8385,11 +8373,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;
@@ -8595,7 +8588,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 {
@@ -8629,7 +8622,7 @@ void invoke_prompt_callback(void)
if (curbuf->b_prompt_callback.type == kCallbackNone) {
return;
}
- char *text = (char *)ml_get(lnum);
+ char *text = ml_get(lnum);
char *prompt = (char *)prompt_text();
if (STRLEN(text) >= STRLEN(prompt)) {
text += STRLEN(prompt);
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index b0cb5fd8c1..afebdf5acb 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -11,33 +11,31 @@
#define COPYID_INC 2
#define COPYID_MASK (~0x1)
-/*
- * Structure returned by get_lval() and used by set_var_lval().
- * For a plain name:
- * "name" points to the variable name.
- * "exp_name" is NULL.
- * "tv" is NULL
- * For a magic braces name:
- * "name" points to the expanded variable name.
- * "exp_name" is non-NULL, to be freed later.
- * "tv" is NULL
- * For an index in a list:
- * "name" points to the (expanded) variable name.
- * "exp_name" NULL or non-NULL, to be freed later.
- * "tv" points to the (first) list item value
- * "li" points to the (first) list item
- * "range", "n1", "n2" and "empty2" indicate what items are used.
- * For an existing Dict item:
- * "name" points to the (expanded) variable name.
- * "exp_name" NULL or non-NULL, to be freed later.
- * "tv" points to the dict item value
- * "newkey" is NULL
- * For a non-existing Dict item:
- * "name" points to the (expanded) variable name.
- * "exp_name" NULL or non-NULL, to be freed later.
- * "tv" points to the Dictionary typval_T
- * "newkey" is the key for the new item.
- */
+// Structure returned by get_lval() and used by set_var_lval().
+// For a plain name:
+// "name" points to the variable name.
+// "exp_name" is NULL.
+// "tv" is NULL
+// For a magic braces name:
+// "name" points to the expanded variable name.
+// "exp_name" is non-NULL, to be freed later.
+// "tv" is NULL
+// For an index in a list:
+// "name" points to the (expanded) variable name.
+// "exp_name" NULL or non-NULL, to be freed later.
+// "tv" points to the (first) list item value
+// "li" points to the (first) list item
+// "range", "n1", "n2" and "empty2" indicate what items are used.
+// For an existing Dict item:
+// "name" points to the (expanded) variable name.
+// "exp_name" NULL or non-NULL, to be freed later.
+// "tv" points to the dict item value
+// "newkey" is NULL
+// For a non-existing Dict item:
+// "name" points to the (expanded) variable name.
+// "exp_name" NULL or non-NULL, to be freed later.
+// "tv" points to the Dictionary typval_T
+// "newkey" is the key for the new item.
typedef struct lval_S {
const char *ll_name; ///< Start of variable name (can be NULL).
size_t ll_name_len; ///< Length of the .ll_name.
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index e4e9b34ec6..5c500af899 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,13 +418,14 @@ 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={},
uniq={args={1, 3}, base=1},
values={args=1, base=1},
virtcol={args=1, base=1},
+ virtcol2col={args=3, base=1},
visualmode={args={0, 1}},
wait={args={2,3}},
wildmenumode={},
diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c
index 7b975ce775..d585509df4 100644
--- a/src/nvim/eval/decode.c
+++ b/src/nvim/eval/decode.c
@@ -430,7 +430,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
const char ubuf[] = { t[1], t[2], t[3], t[4] };
t += 4;
uvarnumber_T ch;
- vim_str2nr((char_u *)ubuf, NULL, NULL,
+ vim_str2nr(ubuf, NULL, NULL,
STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true);
if (ch == 0) {
hasnul = true;
@@ -600,7 +600,7 @@ parse_json_number_check:
// Convert integer
varnumber_T nr;
int num_len;
- vim_str2nr((char_u *)s, NULL, &num_len, 0, &nr, NULL, (int)(p - s), true);
+ vim_str2nr(s, NULL, &num_len, 0, &nr, NULL, (int)(p - s), true);
if ((int)exp_num_len != num_len) {
semsg(_("E685: internal error: while converting number \"%.*s\" "
"to integer vim_str2nr consumed %i bytes in place of %zu"),
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 9c3c859771..8c94586fc9 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.
@@ -420,7 +423,7 @@ static buf_T *find_buffer(typval_T *avar)
FOR_ALL_BUFFERS(bp) {
if (bp->b_fname != NULL
&& (path_with_url(bp->b_fname) || bt_nofilename(bp))
- && STRCMP(bp->b_fname, avar->vval.v_string) == 0) {
+ && strcmp(bp->b_fname, avar->vval.v_string) == 0) {
buf = bp;
break;
}
@@ -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 = 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;
@@ -925,12 +930,12 @@ static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
// Return the current directory
- char_u *cwd = xmalloc(MAXPATHL);
- if (os_dirname(cwd, MAXPATHL) != FAIL) {
+ char *cwd = xmalloc(MAXPATHL);
+ if (os_dirname((char_u *)cwd, MAXPATHL) != FAIL) {
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(cwd);
#endif
- rettv->vval.v_string = (char *)vim_strsave(cwd);
+ rettv->vval.v_string = xstrdup(cwd);
}
xfree(cwd);
@@ -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];
@@ -1029,19 +1034,19 @@ static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
if (!error) {
- rettv->vval.v_number = do_dialog(type, NULL, (char_u *)message, (char_u *)buttons, def, NULL,
+ rettv->vval.v_number = do_dialog(type, NULL, (char *)message, (char *)buttons, def, NULL,
false);
}
}
/// "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;
@@ -1060,7 +1065,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr)
const size_t len = STRLEN(expr);
while (*p != NUL) {
- if (mb_strnicmp(p, expr, len) == 0) {
+ if (mb_strnicmp((char *)p, (char *)expr, len) == 0) {
n++;
p += len;
} else {
@@ -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,15 +1764,15 @@ 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) {
+ if (tv_check_for_string_arg(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,14 +1894,14 @@ 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) {
+ if (tv_check_for_nonempty_string_arg(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) {
@@ -2005,10 +2016,9 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
options += WILD_ICASE;
}
if (rettv->v_type == VAR_STRING) {
- rettv->vval.v_string = (char *)ExpandOne(&xpc, (char_u *)s, NULL, options,
- WILD_ALL);
+ rettv->vval.v_string = ExpandOne(&xpc, (char *)s, NULL, options, WILD_ALL);
} else {
- ExpandOne(&xpc, (char_u *)s, NULL, options, WILD_ALL_KEEP);
+ ExpandOne(&xpc, (char *)s, NULL, options, WILD_ALL_KEEP);
tv_list_alloc_ret(rettv, xpc.xp_numfiles);
for (int i = 0; i < xpc.xp_numfiles; i++) {
tv_list_append_string(rettv->vval.v_list,
@@ -2026,7 +2036,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 +2049,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 +2073,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 +2108,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 +2184,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 +2205,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 +2224,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 +2265,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 +2280,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 +2314,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 +2328,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 +2363,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 +2389,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;
@@ -2426,7 +2436,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
pt = argvars[0].vval.v_partial;
} else {
CLEAR_FIELD(fref_pt);
- fref_pt.pt_name = (char_u *)argvars[0].vval.v_string;
+ fref_pt.pt_name = argvars[0].vval.v_string;
pt = &fref_pt;
}
@@ -2476,7 +2486,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 +2548,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.
@@ -2568,14 +2578,13 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli
}
} else {
rettv->v_type = VAR_STRING;
- rettv->vval.v_string =
- (char *)((start >= 1 && start <= buf->b_ml.ml_line_count)
- ? vim_strsave(ml_get_buf(buf, start, false)) : NULL);
+ rettv->vval.v_string = ((start >= 1 && start <= buf->b_ml.ml_line_count)
+ ? xstrdup(ml_get_buf(buf, start, false)) : NULL);
}
}
/// "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 +2597,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 +2702,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 +2719,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 +2737,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 +2850,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 +2877,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 +2886,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 +2902,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,9 +2915,9 @@ 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 *type = NULL;
char *t;
const char *fname = tv_get_string(&argvars[0]);
@@ -2968,13 +2943,13 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
} else {
t = "other";
}
- type = vim_strsave((char_u *)t);
+ type = xstrdup(t);
}
- rettv->vval.v_string = (char *)type;
+ rettv->vval.v_string = type;
}
/// "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 +2980,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 +2998,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 +3016,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 +3057,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);
}
@@ -3109,23 +3084,23 @@ static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// Returns zero on error.
static int getreg_get_regname(typval_T *argvars)
{
- const char_u *strregname;
+ const char *strregname;
if (argvars[0].v_type != VAR_UNKNOWN) {
- strregname = (const char_u *)tv_get_string_chk(&argvars[0]);
+ strregname = tv_get_string_chk(&argvars[0]);
if (strregname == NULL) { // type error; errmsg already given
return 0;
}
} else {
// Default to v:register
- strregname = (char_u *)get_vim_var_str(VV_REG);
+ strregname = get_vim_var_str(VV_REG);
}
- return *strregname == 0 ? '"' : *strregname;
+ return *strregname == 0 ? '"' : utf_ptr2char(strregname);
}
/// "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 +3136,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 +3156,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 +3188,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 +3205,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 +3250,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 +3304,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 +3351,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 +3389,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 +3397,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;
@@ -3464,11 +3439,11 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr)
options += WILD_ICASE;
}
if (rettv->v_type == VAR_STRING) {
- rettv->vval.v_string = (char *)ExpandOne(&xpc, (char_u *)
- tv_get_string(&argvars[0]), NULL, options,
- WILD_ALL);
+ rettv->vval.v_string = ExpandOne(&xpc, (char *)
+ tv_get_string(&argvars[0]), NULL, options,
+ WILD_ALL);
} else {
- ExpandOne(&xpc, (char_u *)tv_get_string(&argvars[0]), NULL, options,
+ ExpandOne(&xpc, (char *)tv_get_string(&argvars[0]), NULL, options,
WILD_ALL_KEEP);
tv_list_alloc_ret(rettv, xpc.xp_numfiles);
for (int i = 0; i < xpc.xp_numfiles; i++) {
@@ -3483,7 +3458,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 +3489,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 +3508,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 +3517,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__)
@@ -3660,6 +3635,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
"title",
"user-commands", // was accidentally included in 5.4
"user_commands",
+ "usermarks",
"vartabs",
"vertsplit",
"vimscript-1",
@@ -3673,6 +3649,8 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
"winaltkeys",
"writebackup",
"nvim",
+ "userreg",
+ "floattitle",
};
// XXX: eval_has_provider() may shell out :(
@@ -3764,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;
@@ -3854,29 +3832,29 @@ 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];
os_get_hostname(hostname, 256);
rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char *)vim_strsave((char_u *)hostname);
+ rettv->vval.v_string = xstrdup(hostname);
}
/// 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;
@@ -3885,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);
@@ -3904,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) {
@@ -3915,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;
@@ -3990,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()");
@@ -4033,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--;
@@ -4047,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);
@@ -4055,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;
@@ -4138,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;
@@ -4198,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)) {
@@ -4207,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);
@@ -4224,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;
@@ -4248,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;
@@ -4315,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);
@@ -4404,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;
@@ -4479,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;
@@ -4524,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;
@@ -4557,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;
@@ -4656,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;
@@ -4690,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;
@@ -4711,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:
@@ -4782,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;
@@ -4825,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) {
@@ -4839,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);
@@ -4853,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]);
@@ -4871,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);
}
@@ -4893,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) {
@@ -5007,9 +4987,9 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
li = TV_LIST_ITEM_NEXT(l, li);
idx++;
} else {
- startcol = (colnr_T)(regmatch.startp[0]
- + utfc_ptr2len((char *)regmatch.startp[0]) - str);
- if (startcol > (colnr_T)len || str + startcol <= regmatch.startp[0]) {
+ startcol = (colnr_T)((char_u *)regmatch.startp[0]
+ + utfc_ptr2len(regmatch.startp[0]) - str);
+ if (startcol > (colnr_T)len || str + startcol <= (char_u *)regmatch.startp[0]) {
match = false;
break;
}
@@ -5028,8 +5008,8 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
const size_t rd = (size_t)(regmatch.endp[0] - regmatch.startp[0]);
TV_LIST_ITEM_TV(li1)->vval.v_string = xmemdupz((const char *)regmatch.startp[0], rd);
- TV_LIST_ITEM_TV(li3)->vval.v_number = (varnumber_T)(regmatch.startp[0] - expr);
- TV_LIST_ITEM_TV(li4)->vval.v_number = (varnumber_T)(regmatch.endp[0] - expr);
+ TV_LIST_ITEM_TV(li3)->vval.v_number = (varnumber_T)((char_u *)regmatch.startp[0] - expr);
+ TV_LIST_ITEM_TV(li4)->vval.v_number = (varnumber_T)(regmatch.endp[0] - (char *)expr);
if (l != NULL) {
TV_LIST_ITEM_TV(li2)->vval.v_number = (varnumber_T)idx;
}
@@ -5064,10 +5044,10 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
} else {
if (type == kSomeMatch) {
rettv->vval.v_number =
- (varnumber_T)(regmatch.startp[0] - str);
+ (varnumber_T)((char_u *)regmatch.startp[0] - str);
} else {
rettv->vval.v_number =
- (varnumber_T)(regmatch.endp[0] - str);
+ (varnumber_T)(regmatch.endp[0] - (char *)str);
}
rettv->vval.v_number += (varnumber_T)(str - expr);
}
@@ -5089,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);
}
@@ -5168,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
@@ -5225,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];
@@ -5242,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) {
@@ -5381,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) {
@@ -5397,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;
@@ -5406,7 +5386,7 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
lnum = 0;
break;
}
- if (*skipwhite((char *)ml_get(lnum)) != NUL) {
+ if (*skipwhite(ml_get(lnum)) != NUL) {
break;
}
}
@@ -5414,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])) {
@@ -5445,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;
@@ -5464,17 +5444,17 @@ static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
rettv->v_type = VAR_STRING;
- const char_u *p = (char_u *)tv_get_string_chk(&argvars[0]);
+ const char *p = tv_get_string_chk(&argvars[0]);
if (p == NULL) {
rettv->vval.v_string = NULL;
} else {
- rettv->vval.v_string = (char *)vim_strsave(p);
+ rettv->vval.v_string = xstrdup(p);
shorten_dir_len((char_u *)rettv->vval.v_string, trim_len);
}
}
/// "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;
@@ -5488,13 +5468,13 @@ 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) {
lnum = 0;
} else {
- while (lnum >= 1 && *skipwhite((char *)ml_get(lnum)) == NUL) {
+ while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL) {
lnum--;
}
}
@@ -5502,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;
@@ -5524,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 };
@@ -5547,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 };
@@ -5570,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
@@ -5586,11 +5566,11 @@ static void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
- rettv->vval.v_string = (char *)vim_strsave(buf_prompt_text(buf));
+ rettv->vval.v_string = xstrdup(buf_prompt_text(buf));
}
/// "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;
@@ -5606,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;
@@ -5621,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);
}
@@ -5693,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;
@@ -5704,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);
@@ -5763,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;
@@ -5785,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;
@@ -5867,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);
@@ -5885,14 +5865,14 @@ 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;
FILE *fd;
- char_u buf[(IOSIZE/256) * 256]; // rounded to avoid odd + 1
+ char buf[(IOSIZE/256) * 256]; // rounded to avoid odd + 1
int io_size = sizeof(buf);
- char_u *prev = NULL; // previously read bytes, if any
+ char *prev = NULL; // previously read bytes, if any
long prevlen = 0; // length of data in prev
long prevsize = 0; // size of prev buffer
long maxline = MAXLNUM;
@@ -5912,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;
}
@@ -5943,13 +5923,13 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// - an incomplete line gets written
// - a "binary" file gets an empty line at the end if it ends in a
// newline.
- char_u *p; // Position in buf.
- char_u *start; // Start of current line.
+ char *p; // Position in buf.
+ char *start; // Start of current line.
for (p = buf, start = buf;
p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary));
p++) {
if (*p == '\n' || readlen <= 0) {
- char_u *s = NULL;
+ char *s = NULL;
size_t len = (size_t)(p - start);
// Finished a line. Remove CRs before NL.
@@ -5966,7 +5946,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
if (prevlen == 0) {
assert(len < INT_MAX);
- s = vim_strnsave(start, len);
+ s = xstrnsave(start, len);
} else {
// Change "prev" buffer to be the right size. This way
// the bytes are only copied once, and very long lines are
@@ -5981,7 +5961,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_list_append_owned_tv(l, (typval_T) {
.v_type = VAR_STRING,
.v_lock = VAR_UNLOCKED,
- .vval.v_string = (char *)s,
+ .vval.v_string = s,
});
start = p + 1; // Step over newline.
@@ -6001,18 +5981,18 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*p = '\n';
// Check for utf8 "bom"; U+FEFF is encoded as EF BB BF. Do this
// when finding the BF and check the previous two bytes.
- } else if (*p == 0xbf && !binary) {
+ } else if ((uint8_t)(*p) == 0xbf && !binary) {
// Find the two bytes before the 0xbf. If p is at buf, or buf + 1,
// these may be in the "prev" string.
- char_u back1 = p >= buf + 1 ? p[-1]
+ char back1 = p >= buf + 1 ? p[-1]
: prevlen >= 1 ? prev[prevlen - 1] : NUL;
- char_u back2 = p >= buf + 2 ? p[-2]
+ char back2 = p >= buf + 2 ? p[-2]
: p == buf + 1 && prevlen >= 1 ? prev[prevlen - 1]
: prevlen >=
- 2 ? prev[prevlen - 2] : NUL;
+ 2 ? prev[prevlen - 2] : NUL;
- if (back2 == 0xef && back1 == 0xbb) {
- char_u *dest = p - 2;
+ if ((uint8_t)back2 == 0xef && (uint8_t)back1 == 0xbb) {
+ char *dest = p - 2;
// Usually a BOM is at the beginning of a file, and so at
// the beginning of a line; then we can just step over it.
@@ -6068,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) {
@@ -6118,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);
}
@@ -6171,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;
@@ -6213,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;
@@ -6226,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");
@@ -6242,19 +6222,19 @@ 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;
} else {
char buf[NUMBUFLEN];
- rettv->vval.v_number = vim_rename((const char_u *)tv_get_string(&argvars[0]),
- (const char_u *)tv_get_string_buf(&argvars[1], buf));
+ rettv->vval.v_number = vim_rename(tv_get_string(&argvars[0]),
+ tv_get_string_buf(&argvars[1], buf));
}
}
/// "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) {
@@ -6291,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]);
@@ -6302,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
{
@@ -6364,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;
@@ -6423,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) {
@@ -6460,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;
@@ -6485,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));
@@ -6785,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;
@@ -6820,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;
@@ -6909,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;
@@ -6981,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;
@@ -6999,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 =
@@ -7011,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;
@@ -7029,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;
@@ -7047,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;
@@ -7060,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++;
@@ -7075,45 +7055,19 @@ 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)
-{
- tv_dict_alloc_ret(rettv);
- dict_T *dict = rettv->vval.v_dict;
-
- win_T *wp = find_win_by_nr_or_id(&argvars[0]);
- if (wp == NULL) {
- return;
- }
-
- pos_T pos = {
- .lnum = (linenr_T)tv_get_number(&argvars[1]),
- .col = (colnr_T)tv_get_number(&argvars[2]) - 1,
- .coladd = 0
- };
- int row = 0;
- int scol = 0, ccol = 0, ecol = 0;
- textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false);
-
- tv_dict_add_nr(dict, S_LEN("row"), row);
- tv_dict_add_nr(dict, S_LEN("col"), scol);
- tv_dict_add_nr(dict, S_LEN("curscol"), ccol);
- tv_dict_add_nr(dict, S_LEN("endcol"), ecol);
-}
-
/// "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;
@@ -7128,11 +7082,11 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
- rettv->vval.v_string = (char *)vim_strsave(grid->chars[grid->line_offset[row] + (size_t)col]);
+ rettv->vval.v_string = xstrdup((char *)grid->chars[grid->line_offset[row] + (size_t)col]);
}
/// "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;
@@ -7140,7 +7094,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;
@@ -7235,13 +7189,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;
@@ -7283,7 +7237,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);
@@ -7409,18 +7363,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;
@@ -7440,7 +7399,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);
@@ -7454,7 +7413,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
@@ -7499,7 +7458,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;
@@ -7519,7 +7478,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;
@@ -7534,7 +7493,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)
{
@@ -7571,12 +7530,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));
@@ -7588,7 +7547,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));
}
@@ -7604,24 +7563,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];
@@ -7636,7 +7585,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;
@@ -7667,14 +7616,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);
}
@@ -7710,7 +7659,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;
@@ -7836,7 +7785,7 @@ free_lstval:
if (strval == NULL) {
return;
}
- write_reg_contents_ex(regname, (const char_u *)strval, (ssize_t)STRLEN(strval),
+ write_reg_contents_ex(regname, strval, (ssize_t)STRLEN(strval),
append, yank_type, (colnr_T)block_len);
}
if (pointreg != 0) {
@@ -7851,7 +7800,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';
@@ -7902,7 +7851,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);
@@ -7913,7 +7862,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]);
@@ -7924,7 +7873,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;
@@ -7940,7 +7889,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);
@@ -7949,7 +7898,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));
@@ -8001,7 +7950,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));
@@ -8035,7 +7984,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;
@@ -8048,7 +7997,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]);
@@ -8056,7 +8005,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;
@@ -8078,7 +8027,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Find the start and length of the badly spelled word.
len = spell_move_to(curwin, FORWARD, true, true, &attr);
if (len != 0) {
- word = (char *)get_cursor_pos_ptr();
+ word = get_cursor_pos_ptr();
curwin->w_set_curswant = true;
}
} else if (*curbuf->b_s.b_p_spl != NUL) {
@@ -8112,7 +8061,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;
@@ -8159,7 +8108,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;
@@ -8167,7 +8116,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;
@@ -8221,11 +8170,11 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr)
break;
}
// Advance to just after the match.
- if (regmatch.endp[0] > (char_u *)str) {
+ if (regmatch.endp[0] > str) {
col = 0;
} else {
// Don't get stuck at the same match.
- col = utfc_ptr2len((char *)regmatch.endp[0]);
+ col = utfc_ptr2len(regmatch.endp[0]);
}
str = (const char *)regmatch.endp[0];
}
@@ -8238,7 +8187,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;
@@ -8270,7 +8219,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 == '-');
@@ -8286,7 +8235,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]);
@@ -8297,7 +8246,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;
@@ -8330,7 +8279,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
break;
}
varnumber_T n;
- vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, false);
+ vim_str2nr((char *)p, NULL, NULL, what, &n, NULL, 0, false);
// Text after the number is silently ignored.
if (isneg) {
rettv->vval.v_number = -n;
@@ -8340,7 +8289,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;
@@ -8360,13 +8309,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) {
@@ -8380,7 +8328,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);
}
@@ -8392,7 +8340,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;
@@ -8420,7 +8368,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;
@@ -8452,20 +8400,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;
@@ -8488,7 +8436,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;
@@ -8497,11 +8445,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]);
@@ -8509,7 +8457,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);
@@ -8563,7 +8511,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;
@@ -8609,7 +8557,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];
@@ -8623,10 +8571,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
@@ -8641,7 +8589,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]);
@@ -8684,14 +8632,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);
@@ -8714,7 +8662,7 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (retList == 0) {
rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char *)reg_submatch(no);
+ rettv->vval.v_string = reg_submatch(no);
} else {
rettv->v_type = VAR_LIST;
rettv->vval.v_list = reg_submatch_list(no);
@@ -8722,7 +8670,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];
@@ -8751,14 +8699,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);
@@ -8767,12 +8715,12 @@ static void f_swapname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|| buf->b_ml.ml_mfp->mf_fname == NULL) {
rettv->vval.v_string = NULL;
} else {
- rettv->vval.v_string = (char *)vim_strsave(buf->b_ml.ml_mfp->mf_fname);
+ rettv->vval.v_string = xstrdup(buf->b_ml.ml_mfp->mf_fname);
}
}
/// "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);
@@ -8791,7 +8739,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]);
@@ -8878,7 +8826,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]);
@@ -8892,7 +8840,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;
@@ -8934,7 +8882,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);
@@ -8958,18 +8906,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;
@@ -8991,7 +8939,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;
@@ -9077,7 +9025,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]));
@@ -9090,14 +9038,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;
}
@@ -9107,7 +9055,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]);
@@ -9125,14 +9073,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();
+ rettv->vval.v_string = 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;
@@ -9175,7 +9123,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;
@@ -9255,7 +9203,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) {
@@ -9273,7 +9221,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));
@@ -9293,7 +9241,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;
@@ -9325,7 +9273,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));
@@ -9340,27 +9288,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];
@@ -9439,14 +9387,14 @@ 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];
- const char_u *head = (const char_u *)tv_get_string_buf_chk(&argvars[0], buf1);
- const char_u *mask = NULL;
- const char_u *prev;
- const char_u *p;
+ const char *head = tv_get_string_buf_chk(&argvars[0], buf1);
+ const char *mask = NULL;
+ const char *prev;
+ const char *p;
int dir = 0;
rettv->v_type = VAR_STRING;
@@ -9455,8 +9403,13 @@ 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);
+ mask = tv_get_string_buf_chk(&argvars[1], buf2);
if (argvars[2].v_type != VAR_UNKNOWN) {
bool error = false;
// leading or trailing characters to trim
@@ -9494,7 +9447,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
- const char_u *tail = head + STRLEN(head);
+ const char *tail = head + STRLEN(head);
if (dir == 0 || dir == 2) {
// Trim trailing characters
for (; tail > head; tail = prev) {
@@ -9517,11 +9470,11 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
}
- rettv->vval.v_string = (char *)vim_strnsave(head, (size_t)(tail - head));
+ rettv->vval.v_string = xstrnsave(head, (size_t)(tail - head));
}
/// "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;
@@ -9553,7 +9506,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]);
@@ -9572,7 +9525,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);
@@ -9590,7 +9543,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;
@@ -9615,14 +9568,14 @@ 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];
+ char str[2];
rettv->v_type = VAR_STRING;
- str[0] = (char_u)curbuf->b_visual_mode_eval;
+ str[0] = (char)curbuf->b_visual_mode_eval;
str[1] = NUL;
- rettv->vval.v_string = (char *)vim_strsave(str);
+ rettv->vval.v_string = xstrdup(str);
// A non-zero number or non-empty string argument: reset mode.
if (non_zero_arg(&argvars[0])) {
@@ -9631,7 +9584,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;
@@ -9639,20 +9592,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;
@@ -9661,7 +9614,7 @@ static void f_win_gettype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (argvars[0].v_type != VAR_UNKNOWN) {
wp = find_win_by_nr_or_id(&argvars[0]);
if (wp == NULL) {
- rettv->vval.v_string = (char *)vim_strsave((char_u *)"unknown");
+ rettv->vval.v_string = xstrdup("unknown");
return;
}
}
@@ -9679,25 +9632,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;
@@ -9712,7 +9677,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;
@@ -9730,7 +9695,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) {
@@ -9741,25 +9706,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;
@@ -9778,20 +9743,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];
@@ -9818,7 +9783,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;
@@ -9868,7 +9833,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;
@@ -9886,32 +9851,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;
@@ -9989,7 +9954,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..777cdc3013 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -40,6 +40,13 @@
# include "eval/typval.c.generated.h"
#endif
+static char e_string_required_for_argument_nr[]
+ = N_("E1174: String required for argument %d");
+static char e_non_empty_string_required_for_argument_nr[]
+ = N_("E1142: Non-empty string required for argument %d");
+static char e_number_required_for_argument_nr[]
+ = N_("E1210: Number required for argument %d");
+
bool tv_in_free_unref_items = false;
// TODO(ZyX-I): Remove DICT_MAXNEST, make users be non-recursive instead
@@ -831,7 +838,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 +862,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;
@@ -1016,7 +1023,7 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero)
if (sortinfo->item_compare_lc) {
res = strcoll(p1, p2);
} else {
- res = sortinfo->item_compare_ic ? STRICMP(p1, p2): STRCMP(p1, p2);
+ res = sortinfo->item_compare_ic ? STRICMP(p1, p2): strcmp(p1, p2);
}
} else {
double n1, n2;
@@ -1247,15 +1254,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 +1274,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);
}
@@ -1568,7 +1575,7 @@ bool tv_callback_equal(const Callback *cb1, const Callback *cb2)
}
switch (cb1->type) {
case kCallbackFuncref:
- return STRCMP(cb1->data.funcref, cb2->data.funcref) == 0;
+ return strcmp(cb1->data.funcref, cb2->data.funcref) == 0;
case kCallbackPartial:
// FIXME: this is inconsistent with tv_equal but is needed for precision
// maybe change dictwatcheradd to return a watcher id instead?
@@ -2533,7 +2540,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 {
@@ -2777,7 +2784,7 @@ static void tv_dict_list(typval_T *const tv, typval_T *const rettv, const DictLi
switch (what) {
case kDictListKeys:
tv_item.v_type = VAR_STRING;
- tv_item.vval.v_string = (char *)vim_strsave(di->di_key);
+ tv_item.vval.v_string = xstrdup((char *)di->di_key);
break;
case kDictListValues:
tv_copy(&di->di_tv, &tv_item);
@@ -2806,25 +2813,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));
@@ -3717,8 +3724,7 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error)
case VAR_STRING: {
varnumber_T n = 0;
if (tv->vval.v_string != NULL) {
- vim_str2nr((char_u *)tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0,
- false);
+ vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, false);
}
return n;
}
@@ -3801,31 +3807,50 @@ float_T tv_get_float(const typval_T *const tv)
return 0;
}
-// Give an error and return FAIL unless "tv" is a string.
-int tv_check_for_string(const typval_T *const tv)
+/// Give an error and return FAIL unless "args[idx]" is a string.
+int tv_check_for_string_arg(const typval_T *const args, const int idx)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
- if (tv->v_type != VAR_STRING) {
- emsg(_(e_stringreq));
+ if (args[idx].v_type != VAR_STRING) {
+ semsg(_(e_string_required_for_argument_nr), idx + 1);
return FAIL;
}
return OK;
}
-// Give an error and return FAIL unless "tv" is a non-empty string.
-int tv_check_for_nonempty_string(const typval_T *const tv)
+/// Give an error and return FAIL unless "args[idx]" is a non-empty string.
+int tv_check_for_nonempty_string_arg(const typval_T *const args, const int idx)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
- if (tv_check_for_string(tv) == FAIL) {
+ if (tv_check_for_string_arg(args, idx) == FAIL) {
return FAIL;
}
- if (tv->vval.v_string == NULL || *tv->vval.v_string == NUL) {
- emsg(_(e_non_empty_string_required));
+ if (args[idx].vval.v_string == NULL || *args[idx].vval.v_string == NUL) {
+ semsg(_(e_non_empty_string_required_for_argument_nr), idx + 1);
return FAIL;
}
return OK;
}
+/// Give an error and return FAIL unless "args[idx]" is a number.
+int tv_check_for_number_arg(const typval_T *const args, const int idx)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+{
+ if (args[idx].v_type != VAR_NUMBER) {
+ semsg(_(e_number_required_for_argument_nr), idx + 1);
+ return FAIL;
+ }
+ return OK;
+}
+
+/// Check for an optional number argument at "idx"
+int tv_check_for_opt_number_arg(const typval_T *const args, const int idx)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+{
+ return (args[idx].v_type == VAR_UNKNOWN
+ || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL;
+}
+
/// Get the string value of a "stringish" VimL object.
///
/// @param[in] tv Object to get value of.
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index c4bc9f603b..6373ead1a3 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), };
@@ -289,12 +286,6 @@ typedef struct {
/// Number of fixed variables used for arguments
#define FIXVAR_CNT 12
-/// Callback interface for C function reference>
-/// Used for managing functions that were registered with |register_cfunc|
-typedef int (*cfunc_T)(int argcount, typval_T *argvars, typval_T *rettv, void *state); // NOLINT
-/// Callback to clear cfunc_T and any associated state.
-typedef void (*cfunc_free_T)(void *state);
-
// Structure to hold info for a function that is currently being executed.
typedef struct funccall_S funccall_T;
@@ -333,10 +324,7 @@ struct ufunc {
garray_T uf_lines; ///< function lines
int uf_profiling; ///< true when func is being profiled
int uf_prof_initialized;
- // Managing cfuncs
- cfunc_T uf_cb; ///< C function extension callback
- cfunc_free_T uf_cb_free; ///< C function extension free callback
- void *uf_cb_state; ///< State of C function extension.
+ LuaRef uf_luaref; ///< lua callback, used if (uf_flags & FC_LUAREF)
// Profiling the function as a whole.
int uf_tm_count; ///< nr of calls
proftime_T uf_tm_total; ///< time spent in function + children
@@ -363,15 +351,14 @@ struct ufunc {
};
struct partial_S {
- int pt_refcount; ///< Reference count.
- char_u *pt_name; ///< Function name; when NULL use pt_func->name.
- ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with
- ///< pt_name.
- bool pt_auto; ///< When true the partial was created by using dict.member
- ///< in handle_subscript().
- int pt_argc; ///< Number of arguments.
+ int pt_refcount; ///< Reference count.
+ char *pt_name; ///< Function name; when NULL use pt_func->name.
+ ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with pt_name.
+ bool pt_auto; ///< When true the partial was created by using dict.member
+ ///< in handle_subscript().
+ int pt_argc; ///< Number of arguments.
typval_T *pt_argv; ///< Arguments in allocated array.
- dict_T *pt_dict; ///< Dict for "self".
+ dict_T *pt_dict; ///< Dict for "self".
};
/// Structure used for explicit stack while garbage collecting hash tables
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 7f64b39cd8..82709b044b 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -28,20 +28,6 @@
#include "nvim/ui.h"
#include "nvim/vim.h"
-// flags used in uf_flags
-#define FC_ABORT 0x01 // abort function on error
-#define FC_RANGE 0x02 // function accepts range
-#define FC_DICT 0x04 // Dict function, uses "self"
-#define FC_CLOSURE 0x08 // closure, uses outer scope variables
-#define FC_DELETED 0x10 // :delfunction used while uf_refcount > 0
-#define FC_REMOVED 0x20 // function redefined while uf_refcount > 0
-#define FC_SANDBOX 0x40 // function defined in the sandbox
-#define FC_DEAD 0x80 // function kept only for reference to dfunc
-#define FC_EXPORT 0x100 // "export def Func()"
-#define FC_NOARGS 0x200 // no a: variables in lambda
-#define FC_VIM9 0x400 // defined in vim9 script file
-#define FC_CFUNC 0x800 // C function extension
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/userfunc.c.generated.h"
#endif
@@ -125,7 +111,7 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
// Check for duplicate argument name.
for (i = 0; i < newargs->ga_len; i++) {
- if (STRCMP(((char **)(newargs->ga_data))[i], arg) == 0) {
+ if (strcmp(((char **)(newargs->ga_data))[i], arg) == 0) {
semsg(_("E853: Duplicate argument name: %s"), arg);
xfree(arg);
goto err_ret;
@@ -142,18 +128,18 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
any_default = true;
p = skipwhite(p) + 1;
p = skipwhite(p);
- char_u *expr = (char_u *)p;
+ char *expr = p;
if (eval1(&p, &rettv, false) != FAIL) {
ga_grow(default_args, 1);
// trim trailing whitespace
- while (p > (char *)expr && ascii_iswhite(p[-1])) {
+ while (p > expr && ascii_iswhite(p[-1])) {
p--;
}
c = (char_u)(*p);
*p = NUL;
- expr = vim_strsave(expr);
- ((char **)(default_args->ga_data))[default_args->ga_len] = (char *)expr;
+ expr = xstrdup(expr);
+ ((char **)(default_args->ga_data))[default_args->ga_len] = expr;
default_args->ga_len++;
*p = (char)c;
} else {
@@ -378,7 +364,7 @@ char_u *deref_func_name(const char *name, int *lenp, partial_T **const partialp,
*lenp = 0;
return (char_u *)"";
}
- *lenp = (int)STRLEN(v->di_tv.vval.v_string);
+ *lenp = (int)strlen(v->di_tv.vval.v_string);
return (char_u *)v->di_tv.vval.v_string;
}
@@ -409,7 +395,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;
}
@@ -525,22 +511,22 @@ static inline bool eval_fname_sid(const char *const name)
///
/// @return transformed name: either `fname_buf` or a pointer to an allocated
/// memory.
-static char_u *fname_trans_sid(const char_u *const name, char_u *const fname_buf,
- char_u **const tofree, int *const error)
+static char *fname_trans_sid(const char *const name, char *const fname_buf, char **const tofree,
+ int *const error)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
- char_u *fname;
- const int llen = eval_fname_script((const char *)name);
+ char *fname;
+ const int llen = eval_fname_script(name);
if (llen > 0) {
- fname_buf[0] = K_SPECIAL;
- fname_buf[1] = KS_EXTRA;
+ fname_buf[0] = (char)K_SPECIAL;
+ fname_buf[1] = (char)KS_EXTRA;
fname_buf[2] = KE_SNR;
int i = 3;
- if (eval_fname_sid((const char *)name)) { // "<SID>" or "s:"
+ if (eval_fname_sid(name)) { // "<SID>" or "s:"
if (current_sctx.sc_sid <= 0) {
*error = ERROR_SCRIPT;
} else {
- snprintf((char *)fname_buf + i, (size_t)(FLEN_FIXED + 1 - i), "%" PRId64 "_",
+ snprintf(fname_buf + i, (size_t)(FLEN_FIXED + 1 - i), "%" PRId64 "_",
(int64_t)current_sctx.sc_sid);
i = (int)STRLEN(fname_buf);
}
@@ -555,7 +541,7 @@ static char_u *fname_trans_sid(const char_u *const name, char_u *const fname_buf
STRCPY(fname + i, name + llen);
}
} else {
- fname = (char_u *)name;
+ fname = (char *)name;
}
return fname;
@@ -758,9 +744,9 @@ static void func_clear_items(ufunc_T *fp)
ga_clear_strings(&(fp->uf_lines));
XFREE_CLEAR(fp->uf_name_exp);
- if (fp->uf_cb_free != NULL) {
- fp->uf_cb_free(fp->uf_cb_state);
- fp->uf_cb_free = NULL;
+ if (fp->uf_flags & FC_LUAREF) {
+ api_free_luaref(fp->uf_luaref);
+ fp->uf_luaref = LUA_NOREF;
}
XFREE_CLEAR(fp->uf_tml_count);
@@ -856,7 +842,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
@@ -867,7 +853,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.
@@ -897,7 +883,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).
@@ -974,11 +960,11 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
snprintf((char *)numbuf, sizeof(numbuf), "%d", ai + 1);
name = (char *)numbuf;
}
- if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN) {
+ if (fixvar_idx < FIXVAR_CNT && strlen(name) <= VAR_SHORT_LEN) {
v = (dictitem_T *)&fc->fixvar[fixvar_idx++];
v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
} else {
- v = xmalloc(sizeof(dictitem_T) + STRLEN(name));
+ v = xmalloc(sizeof(dictitem_T) + strlen(name));
v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC;
}
STRCPY(v->di_key, name);
@@ -1062,7 +1048,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;
@@ -1075,7 +1061,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();
}
@@ -1087,7 +1073,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;
@@ -1443,10 +1429,10 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
int ret = FAIL;
int error = ERROR_NONE;
ufunc_T *fp = NULL;
- char_u fname_buf[FLEN_FIXED + 1];
- char_u *tofree = NULL;
- char_u *fname = NULL;
- char_u *name = NULL;
+ char fname_buf[FLEN_FIXED + 1];
+ char *tofree = NULL;
+ char *fname = NULL;
+ char *name = NULL;
int argcount = argcount_in;
typval_T *argvars = argvars_in;
dict_T *selfdict = funcexe->selfdict;
@@ -1461,7 +1447,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
rettv->v_type = VAR_UNKNOWN;
if (len <= 0) {
- len = (int)STRLEN(funcname);
+ len = (int)strlen(funcname);
}
if (partial != NULL) {
fp = partial->pt_func;
@@ -1469,8 +1455,8 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
if (fp == NULL) {
// Make a copy of the name, if it comes from a funcref variable it could
// be changed or deleted in the called function.
- name = vim_strnsave((char_u *)funcname, (size_t)len);
- fname = fname_trans_sid(name, fname_buf, &tofree, &error);
+ name = xstrnsave(funcname, (size_t)len);
+ fname = fname_trans_sid(name, (char *)fname_buf, &tofree, &error);
}
if (funcexe->doesrange != NULL) {
@@ -1501,7 +1487,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
}
if (error == ERROR_NONE && funcexe->evaluate) {
- char_u *rfname = fname;
+ char *rfname = fname;
// Ignore "g:" before a function name.
if (fp == NULL && fname[0] == 'g' && fname[1] == ':') {
@@ -1525,28 +1511,27 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
} else if (fp != NULL || !builtin_function((const char *)rfname, -1)) {
// User defined function.
if (fp == NULL) {
- fp = find_func(rfname);
+ fp = find_func((char_u *)rfname);
}
// Trigger FuncUndefined event, may load the function.
if (fp == NULL
- && apply_autocmds(EVENT_FUNCUNDEFINED, (char *)rfname, (char *)rfname, true, NULL)
+ && apply_autocmds(EVENT_FUNCUNDEFINED, rfname, rfname, true, NULL)
&& !aborting()) {
// executed an autocommand, search for the function again
- fp = find_func(rfname);
+ fp = find_func((char_u *)rfname);
}
// Try loading a package.
if (fp == NULL && script_autoload((const char *)rfname, STRLEN(rfname),
true) && !aborting()) {
// Loaded a package, search for the function again.
- fp = find_func(rfname);
+ fp = find_func((char_u *)rfname);
}
if (fp != NULL && (fp->uf_flags & FC_DELETED)) {
error = ERROR_DELETED;
- } else if (fp != NULL && (fp->uf_flags & FC_CFUNC)) {
- cfunc_T cb = fp->uf_cb;
- error = (*cb)(argcount, argvars, rettv, fp->uf_cb_state);
+ } else if (fp != NULL && (fp->uf_flags & FC_LUAREF)) {
+ error = typval_exec_lua_callable(fp->uf_luaref, argcount, argvars, rettv);
} else if (fp != NULL) {
if (funcexe->argv_func != NULL) {
// postponed filling in the arguments, do it now
@@ -1576,22 +1561,20 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
} else if (funcexe->basetv != NULL) {
// expr->method(): Find the method name in the table, call its
// implementation with the base as one of the arguments.
- error = call_internal_method(fname, argcount, argvars, rettv,
+ error = call_internal_method((char_u *)fname, argcount, argvars, rettv,
funcexe->basetv);
} else {
// Find the function name in the table, call its implementation.
- error = call_internal_func(fname, argcount, argvars, rettv);
- }
- /*
- * The function call (or "FuncUndefined" autocommand sequence) might
- * have been aborted by an error, an interrupt, or an explicitly thrown
- * exception that has not been caught so far. This situation can be
- * tested for by calling aborting(). For an error in an internal
- * function or for the "E132" error in call_user_func(), however, the
- * throw point at which the "force_abort" flag (temporarily reset by
- * emsg()) is normally updated has not been reached yet. We need to
- * update that flag first to make aborting() reliable.
- */
+ error = call_internal_func((char_u *)fname, argcount, argvars, rettv);
+ }
+ // The function call (or "FuncUndefined" autocommand sequence) might
+ // have been aborted by an error, an interrupt, or an explicitly thrown
+ // exception that has not been caught so far. This situation can be
+ // tested for by calling aborting(). For an error in an internal
+ // function or for the "E132" error in call_user_func(), however, the
+ // throw point at which the "force_abort" flag (temporarily reset by
+ // emsg()) is normally updated has not been reached yet. We need to
+ // update that flag first to make aborting() reliable.
update_force_abort();
}
if (error == ERROR_NONE) {
@@ -1602,7 +1585,7 @@ theend:
// Report an error unless the argument evaluation or function call has been
// cancelled due to an aborting error, an interrupt, or an exception.
if (!aborting()) {
- user_func_error(error, (name != NULL) ? name : (char_u *)funcname);
+ user_func_error(error, (name != NULL) ? (char_u *)name : (char_u *)funcname);
}
// clear the copies made from the partial
@@ -1688,7 +1671,7 @@ static void list_func_head(ufunc_T *fp, int indent, bool force)
char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, partial_T **partial)
FUNC_ATTR_NONNULL_ARG(1)
{
- char_u *name = NULL;
+ char *name = NULL;
const char_u *start;
const char_u *end;
int lead;
@@ -1726,11 +1709,9 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
goto theend;
}
if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range))) {
- /*
- * Report an invalid expression in braces, unless the expression
- * evaluation has been cancelled due to an aborting error, an
- * interrupt, or an exception.
- */
+ // Report an invalid expression in braces, unless the expression
+ // evaluation has been cancelled due to an aborting error, an
+ // interrupt, or an exception.
if (!aborting()) {
if (end != NULL) {
semsg(_(e_invarg2), start);
@@ -1749,7 +1730,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
fdp->fd_di = lv.ll_di;
}
if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL) {
- name = vim_strsave((char_u *)lv.ll_tv->vval.v_string);
+ name = xstrdup(lv.ll_tv->vval.v_string);
*pp = (char *)end;
} else if (lv.ll_tv->v_type == VAR_PARTIAL
&& lv.ll_tv->vval.v_partial != NULL) {
@@ -1763,7 +1744,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
memcpy(name, end + 1, (size_t)len);
*pp = (char *)end + 1 + len;
} else {
- name = vim_strsave((char_u *)partial_name(lv.ll_tv->vval.v_partial));
+ name = xstrdup(partial_name(lv.ll_tv->vval.v_partial));
*pp = (char *)end;
}
if (partial != NULL) {
@@ -1791,28 +1772,28 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
// Check if the name is a Funcref. If so, use the value.
if (lv.ll_exp_name != NULL) {
len = (int)strlen(lv.ll_exp_name);
- name = deref_func_name(lv.ll_exp_name, &len, partial,
- flags & TFN_NO_AUTOLOAD);
+ name = (char *)deref_func_name(lv.ll_exp_name, &len, partial,
+ flags & TFN_NO_AUTOLOAD);
if ((const char *)name == lv.ll_exp_name) {
name = NULL;
}
} else if (!(flags & TFN_NO_DEREF)) {
len = (int)(end - (char_u *)(*pp));
- name = deref_func_name((const char *)(*pp), &len, partial,
- flags & TFN_NO_AUTOLOAD);
- if (name == (char_u *)(*pp)) {
+ name = (char *)deref_func_name((const char *)(*pp), &len, partial,
+ flags & TFN_NO_AUTOLOAD);
+ if (name == *pp) {
name = NULL;
}
}
if (name != NULL) {
- name = vim_strsave(name);
+ name = xstrdup(name);
*pp = (char *)end;
if (STRNCMP(name, "<SNR>", 5) == 0) {
// Change "<SNR>" to the byte sequence.
- name[0] = K_SPECIAL;
- name[1] = KS_EXTRA;
+ name[0] = (char)K_SPECIAL;
+ name[1] = (char)KS_EXTRA;
name[2] = KE_SNR;
- memmove(name + 3, name + 5, strlen((char *)name + 5) + 1);
+ memmove(name + 3, name + 5, strlen(name + 5) + 1);
}
goto theend;
}
@@ -1875,8 +1856,8 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
name = xmalloc((size_t)len + (size_t)lead + 1);
if (!skip && lead > 0) {
- name[0] = K_SPECIAL;
- name[1] = KS_EXTRA;
+ name[0] = (char)K_SPECIAL;
+ name[1] = (char)KS_EXTRA;
name[2] = KE_SNR;
if (sid_buf_len > 0) { // If it's "<SID>"
memcpy(name + 3, sid_buf, sid_buf_len);
@@ -1888,21 +1869,23 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
theend:
clear_lval(&lv);
- return name;
+ return (char_u *)name;
}
+#define MAX_FUNC_NESTING 50
+
/// ":function"
void ex_function(exarg_T *eap)
{
- char_u *theline;
- char_u *line_to_free = NULL;
- char_u c;
+ char *theline;
+ char *line_to_free = NULL;
+ char c;
int saved_did_emsg;
bool saved_wait_return = need_wait_return;
- char_u *name = NULL;
- char_u *p;
- char_u *arg;
- char_u *line_arg = NULL;
+ char *name = NULL;
+ char *p;
+ char *arg;
+ char *line_arg = NULL;
garray_T newargs;
garray_T default_args;
garray_T newlines;
@@ -1922,22 +1905,20 @@ void ex_function(exarg_T *eap)
linenr_T sourcing_lnum_off;
linenr_T sourcing_lnum_top;
bool is_heredoc = false;
- char_u *skip_until = NULL;
- char_u *heredoc_trimmed = NULL;
+ char *skip_until = NULL;
+ char *heredoc_trimmed = NULL;
bool show_block = false;
bool do_concat = true;
- /*
- * ":function" without argument: list functions.
- */
+ // ":function" without argument: list functions.
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)) {
@@ -1946,15 +1927,13 @@ void ex_function(exarg_T *eap)
}
}
}
- eap->nextcmd = (char *)check_nextcmd((char_u *)eap->arg);
+ eap->nextcmd = check_nextcmd(eap->arg);
return;
}
- /*
- * ":function /pat": list functions matching pattern.
- */
+ // ":function /pat": list functions matching pattern.
if (*eap->arg == '/') {
- p = skip_regexp((char_u *)eap->arg + 1, '/', true, NULL);
+ p = skip_regexp(eap->arg + 1, '/', true, NULL);
if (!eap->skip) {
regmatch_T regmatch;
@@ -1966,7 +1945,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);
@@ -1982,7 +1961,7 @@ void ex_function(exarg_T *eap)
if (*p == '/') {
p++;
}
- eap->nextcmd = (char *)check_nextcmd(p);
+ eap->nextcmd = check_nextcmd(p);
return;
}
@@ -2000,15 +1979,13 @@ void ex_function(exarg_T *eap)
// "fudi.fd_di" set, "fudi.fd_newkey" == NULL
// s:func script-local function name
// g:func global function name, same as "func"
- p = (char_u *)eap->arg;
- name = trans_function_name((char **)&p, eap->skip, TFN_NO_AUTOLOAD, &fudi, NULL);
- paren = (vim_strchr((char *)p, '(') != NULL);
+ p = eap->arg;
+ name = (char *)trans_function_name(&p, eap->skip, TFN_NO_AUTOLOAD, &fudi, NULL);
+ paren = (vim_strchr(p, '(') != NULL);
if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) {
- /*
- * Return on an invalid expression in braces, unless the expression
- * evaluation has been cancelled due to an aborting error, an
- * interrupt, or an exception.
- */
+ // Return on an invalid expression in braces, unless the expression
+ // evaluation has been cancelled due to an aborting error, an
+ // interrupt, or an exception.
if (!aborting()) {
if (fudi.fd_newkey != NULL) {
semsg(_(e_dictkey), fudi.fd_newkey);
@@ -2016,14 +1993,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.
@@ -2032,16 +2009,16 @@ void ex_function(exarg_T *eap)
// - exclude line numbers from function body
//
if (!paren) {
- if (!ends_excmd(*skipwhite((char *)p))) {
+ if (!ends_excmd(*skipwhite(p))) {
semsg(_(e_trailing_arg), p);
goto ret_free;
}
- eap->nextcmd = (char *)check_nextcmd(p);
+ eap->nextcmd = check_nextcmd(p);
if (eap->nextcmd != NULL) {
*p = NUL;
}
if (!eap->skip && !got_int) {
- fp = find_func(name);
+ fp = find_func((char_u *)name);
if (fp != NULL) {
list_func_head(fp, !eap->forceit, eap->forceit);
for (int j = 0; j < fp->uf_lines.ga_len && !got_int; j++) {
@@ -2058,7 +2035,7 @@ void ex_function(exarg_T *eap)
msg_putchar(' ');
}
}
- msg_prt_line((char_u *)FUNCLINE(fp, j), false);
+ msg_prt_line(FUNCLINE(fp, j), false);
ui_flush(); // show a line at a time
os_breakcheck();
}
@@ -2067,27 +2044,25 @@ void ex_function(exarg_T *eap)
msg_puts(eap->forceit ? "endfunction" : " endfunction");
}
} else {
- emsg_funcname(N_("E123: Undefined function: %s"), name);
+ emsg_funcname(N_("E123: Undefined function: %s"), (char_u *)name);
}
}
goto ret_free;
}
- /*
- * ":function name(arg1, arg2)" Define function.
- */
- p = (char_u *)skipwhite((char *)p);
+ // ":function name(arg1, arg2)" Define function.
+ p = skipwhite(p);
if (*p != '(') {
if (!eap->skip) {
semsg(_("E124: Missing '(': %s"), eap->arg);
goto ret_free;
}
// attempt to continue by skipping some text
- if (vim_strchr((char *)p, '(') != NULL) {
- p = (char_u *)vim_strchr((char *)p, '(');
+ if (vim_strchr(p, '(') != NULL) {
+ p = vim_strchr(p, '(');
}
}
- p = (char_u *)skipwhite((char *)p + 1);
+ p = skipwhite(p + 1);
ga_init(&newargs, (int)sizeof(char_u *), 3);
ga_init(&newlines, (int)sizeof(char_u *), 3);
@@ -2098,15 +2073,15 @@ void ex_function(exarg_T *eap)
if (name != NULL) {
arg = name;
} else {
- arg = fudi.fd_newkey;
+ arg = (char *)fudi.fd_newkey;
}
if (arg != NULL && (fudi.fd_di == NULL || !tv_is_func(fudi.fd_di->di_tv))) {
- int j = (*arg == K_SPECIAL) ? 3 : 0;
+ int j = ((uint8_t)(*arg) == K_SPECIAL) ? 3 : 0;
while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j]) : eval_isnamec(arg[j]))) {
j++;
}
if (arg[j] != NUL) {
- emsg_funcname((char *)e_invarg2, arg);
+ emsg_funcname((char *)e_invarg2, (char_u *)arg);
}
}
// Disallow using the g: dict.
@@ -2115,7 +2090,7 @@ void ex_function(exarg_T *eap)
}
}
- if (get_function_args((char **)&p, ')', &newargs, &varargs,
+ if (get_function_args(&p, ')', &newargs, &varargs,
&default_args, eap->skip) == FAIL) {
goto errret_2;
}
@@ -2127,7 +2102,7 @@ void ex_function(exarg_T *eap)
// find extra arguments "range", "dict", "abort" and "closure"
for (;;) {
- p = (char_u *)skipwhite((char *)p);
+ p = skipwhite(p);
if (STRNCMP(p, "range", 5) == 0) {
flags |= FC_RANGE;
p += 5;
@@ -2141,9 +2116,8 @@ void ex_function(exarg_T *eap)
flags |= FC_CLOSURE;
p += 7;
if (current_funccal == NULL) {
- emsg_funcname(N_
- ("E932: Closure function should not be at top level: %s"),
- name == NULL ? (char_u *)"" : name);
+ emsg_funcname(N_("E932: Closure function should not be at top level: %s"),
+ name == NULL ? (char_u *)"" : (char_u *)name);
goto erret;
}
} else {
@@ -2159,9 +2133,7 @@ void ex_function(exarg_T *eap)
semsg(_(e_trailing_arg), p);
}
- /*
- * Read the body of the function, until ":endfunction" is found.
- */
+ // Read the body of the function, until ":endfunction" is found.
if (KeyTyped) {
// Check if the function already exists, don't let the user type the
// whole function before telling him it doesn't work! For a script we
@@ -2169,8 +2141,8 @@ void ex_function(exarg_T *eap)
if (!eap->skip && !eap->forceit) {
if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) {
emsg(_(e_funcdict));
- } else if (name != NULL && find_func(name) != NULL) {
- emsg_funcname(e_funcexts, name);
+ } else if (name != NULL && find_func((char_u *)name) != NULL) {
+ emsg_funcname(e_funcexts, (char_u *)name);
}
}
@@ -2199,7 +2171,7 @@ void ex_function(exarg_T *eap)
if (line_arg != NULL) {
// Use eap->arg, split up in parts by line breaks.
theline = line_arg;
- p = (char_u *)vim_strchr((char *)theline, '\n');
+ p = vim_strchr(theline, '\n');
if (p == NULL) {
line_arg += STRLEN(line_arg);
} else {
@@ -2209,9 +2181,9 @@ void ex_function(exarg_T *eap)
} else {
xfree(line_to_free);
if (eap->getline == NULL) {
- theline = getcmdline(':', 0L, indent, do_concat);
+ theline = (char *)getcmdline(':', 0L, indent, do_concat);
} else {
- theline = (char_u *)eap->getline(':', eap->cookie, indent, do_concat);
+ theline = eap->getline(':', eap->cookie, indent, do_concat);
}
line_to_free = theline;
}
@@ -2241,18 +2213,18 @@ void ex_function(exarg_T *eap)
// * ":python <<EOF" and "EOF"
// * ":let {var-name} =<< [trim] {marker}" and "{marker}"
if (heredoc_trimmed == NULL
- || (is_heredoc && (char_u *)skipwhite((char *)theline) == theline)
+ || (is_heredoc && skipwhite(theline) == theline)
|| STRNCMP(theline, heredoc_trimmed,
STRLEN(heredoc_trimmed)) == 0) {
if (heredoc_trimmed == NULL) {
p = theline;
} else if (is_heredoc) {
- p = (char_u *)skipwhite((char *)theline) == theline
+ p = skipwhite(theline) == theline
? theline : theline + STRLEN(heredoc_trimmed);
} else {
p = theline + STRLEN(heredoc_trimmed);
}
- if (STRCMP(p, skip_until) == 0) {
+ if (strcmp(p, skip_until) == 0) {
XFREE_CLEAR(skip_until);
XFREE_CLEAR(heredoc_trimmed);
do_concat = true;
@@ -2264,27 +2236,26 @@ void ex_function(exarg_T *eap)
for (p = theline; ascii_iswhite(*p) || *p == ':'; p++) {}
// Check for "endfunction".
- if (checkforcmd((char **)&p, "endfunction", 4) && nesting-- == 0) {
+ if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0) {
if (*p == '!') {
p++;
}
- char_u *nextcmd = NULL;
+ char *nextcmd = NULL;
if (*p == '|') {
nextcmd = p + 1;
- } else if (line_arg != NULL && *skipwhite((char *)line_arg) != NUL) {
+ } else if (line_arg != NULL && *skipwhite(line_arg) != NUL) {
nextcmd = line_arg;
} else if (*p != NUL && *p != '"' && p_verbose > 0) {
- give_warning2((char_u *)_("W22: Text found after :endfunction: %s"),
- p, true);
+ give_warning2(_("W22: Text found after :endfunction: %s"), p, true);
}
if (nextcmd != NULL) {
// Another command follows. If the line came from "eap" we
// can simply point into it, otherwise we need to change
// "eap->cmdlinep".
- eap->nextcmd = (char *)nextcmd;
+ eap->nextcmd = nextcmd;
if (line_to_free != NULL) {
xfree(*eap->cmdlinep);
- *eap->cmdlinep = (char *)line_to_free;
+ *eap->cmdlinep = line_to_free;
line_to_free = NULL;
}
}
@@ -2303,20 +2274,24 @@ void ex_function(exarg_T *eap)
}
// Check for defining a function inside this function.
- if (checkforcmd((char **)&p, "function", 2)) {
+ if (checkforcmd(&p, "function", 2)) {
if (*p == '!') {
- p = (char_u *)skipwhite((char *)p + 1);
+ p = skipwhite(p + 1);
}
p += eval_fname_script((const char *)p);
- xfree(trans_function_name((char **)&p, true, 0, NULL, NULL));
- if (*skipwhite((char *)p) == '(') {
- nesting++;
- indent += 2;
+ xfree(trans_function_name(&p, true, 0, NULL, NULL));
+ if (*skipwhite(p) == '(') {
+ if (nesting == MAX_FUNC_NESTING - 1) {
+ emsg(_("E1058: function nesting too deep"));
+ } else {
+ nesting++;
+ indent += 2;
+ }
}
}
// Check for ":append", ":change", ":insert".
- p = (char_u *)skip_range((char *)p, NULL);
+ p = skip_range(p, NULL);
if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
|| (p[0] == 'c'
&& (!ASCII_ISALPHA(p[1])
@@ -2328,11 +2303,11 @@ void ex_function(exarg_T *eap)
&& (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
&& (!ASCII_ISALPHA(p[2])
|| (p[2] == 's')))))) {
- skip_until = vim_strsave((char_u *)".");
+ skip_until = xstrdup(".");
}
// heredoc: Check for ":python <<EOF", ":lua <<EOF", etc.
- arg = (char_u *)skipwhite((char *)skiptowhite(p));
+ arg = skipwhite(skiptowhite(p));
if (arg[0] == '<' && arg[1] == '<'
&& ((p[0] == 'p' && p[1] == 'y'
&& (!ASCII_ISALNUM(p[2]) || p[2] == 't'
@@ -2349,22 +2324,22 @@ void ex_function(exarg_T *eap)
|| (p[0] == 'm' && p[1] == 'z'
&& (!ASCII_ISALPHA(p[2]) || p[2] == 's')))) {
// ":python <<" continues until a dot, like ":append"
- p = (char_u *)skipwhite((char *)arg + 2);
+ p = skipwhite(arg + 2);
if (*p == NUL) {
- skip_until = vim_strsave((char_u *)".");
+ skip_until = xstrdup(".");
} else {
- skip_until = vim_strsave(p);
+ skip_until = xstrdup(p);
}
}
// Check for ":let v =<< [trim] EOF"
// and ":let [a, b] =<< [trim] EOF"
- arg = (char_u *)skipwhite((char *)skiptowhite(p));
+ arg = skipwhite(skiptowhite(p));
if (*arg == '[') {
- arg = (char_u *)vim_strchr((char *)arg, ']');
+ arg = vim_strchr(arg, ']');
}
if (arg != NULL) {
- arg = (char_u *)skipwhite((char *)skiptowhite(arg));
+ arg = skipwhite(skiptowhite(arg));
if (arg[0] == '='
&& arg[1] == '<'
&& arg[2] == '<'
@@ -2372,14 +2347,13 @@ void ex_function(exarg_T *eap)
&& p[1] == 'e'
&& (!ASCII_ISALNUM(p[2])
|| (p[2] == 't' && !ASCII_ISALNUM(p[3]))))) {
- p = (char_u *)skipwhite((char *)arg + 3);
+ p = skipwhite(arg + 3);
if (STRNCMP(p, "trim", 4) == 0) {
// Ignore leading white space.
- p = (char_u *)skipwhite((char *)p + 4);
- heredoc_trimmed =
- vim_strnsave(theline, (size_t)((char_u *)skipwhite((char *)theline) - theline));
+ p = skipwhite(p + 4);
+ heredoc_trimmed = xstrnsave(theline, (size_t)(skipwhite(theline) - theline));
}
- skip_until = vim_strnsave(p, (size_t)(skiptowhite(p) - p));
+ skip_until = xstrnsave(p, (size_t)(skiptowhite(p) - p));
do_concat = false;
is_heredoc = true;
}
@@ -2392,8 +2366,8 @@ void ex_function(exarg_T *eap)
// Copy the line to newly allocated memory. get_one_sourceline()
// allocates 250 bytes per line, this saves 80% on average. The cost
// is an extra alloc/free.
- p = vim_strsave(theline);
- ((char **)(newlines.ga_data))[newlines.ga_len++] = (char *)p;
+ p = xstrdup(theline);
+ ((char **)(newlines.ga_data))[newlines.ga_len++] = p;
// Add NULL lines for continuation lines, so that the line count is
// equal to the index in the growarray.
@@ -2413,30 +2387,28 @@ void ex_function(exarg_T *eap)
goto erret;
}
- /*
- * If there are no errors, add the function
- */
+ // If there are no errors, add the function
if (fudi.fd_dict == NULL) {
v = find_var((const char *)name, STRLEN(name), &ht, false);
if (v != NULL && v->di_tv.v_type == VAR_FUNC) {
emsg_funcname(N_("E707: Function name conflicts with variable: %s"),
- name);
+ (char_u *)name);
goto erret;
}
- fp = find_func(name);
+ fp = find_func((char_u *)name);
if (fp != NULL) {
// Function can be replaced with "function!" and when sourcing the
// same script again, but only once.
if (!eap->forceit
&& (fp->uf_script_ctx.sc_sid != current_sctx.sc_sid
|| fp->uf_script_ctx.sc_seq == current_sctx.sc_seq)) {
- emsg_funcname(e_funcexts, name);
+ emsg_funcname(e_funcexts, (char_u *)name);
goto erret;
}
if (fp->uf_calls > 0) {
emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"),
- name);
+ (char_u *)name);
goto erret;
}
if (fp->uf_refcount > 1) {
@@ -2480,12 +2452,12 @@ void ex_function(exarg_T *eap)
// Give the function a sequential number. Can only be used with a
// Funcref!
xfree(name);
- sprintf(numbuf, "%d", ++func_nr);
- name = vim_strsave((char_u *)numbuf);
+ sprintf(numbuf, "%d", ++func_nr); // NOLINT(runtime/printf)
+ name = xstrdup(numbuf);
}
if (fp == NULL) {
- if (fudi.fd_dict == NULL && vim_strchr((char *)name, AUTOLOAD_CHAR) != NULL) {
+ if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL) {
int slen, plen;
char_u *scriptname;
@@ -2493,10 +2465,10 @@ void ex_function(exarg_T *eap)
int j = FAIL;
if (SOURCING_NAME != NULL) {
scriptname = (char_u *)autoload_name((const char *)name, STRLEN(name));
- p = (char_u *)vim_strchr((char *)scriptname, '/');
+ p = vim_strchr((char *)scriptname, '/');
plen = (int)STRLEN(p);
slen = (int)STRLEN(SOURCING_NAME);
- if (slen > plen && FNAMECMP(p, SOURCING_NAME + slen - plen) == 0) {
+ if (slen > plen && path_fnamecmp(p, SOURCING_NAME + slen - plen) == 0) {
j = OK;
}
xfree(scriptname);
@@ -2524,16 +2496,16 @@ void ex_function(exarg_T *eap)
tv_clear(&fudi.fd_di->di_tv);
}
fudi.fd_di->di_tv.v_type = VAR_FUNC;
- fudi.fd_di->di_tv.vval.v_string = (char *)vim_strsave(name);
+ fudi.fd_di->di_tv.vval.v_string = xstrdup(name);
// behave like "dict" was used
flags |= FC_DICT;
}
// insert the new function in the function list
- set_ufunc_name(fp, name);
+ set_ufunc_name(fp, (char_u *)name);
if (overwrite) {
- hi = hash_find(&func_hashtab, (char *)name);
+ hi = hash_find(&func_hashtab, name);
hi->hi_key = UF2HIKEY(fp);
} else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) {
xfree(fp);
@@ -2590,8 +2562,8 @@ int eval_fname_script(const char *const p)
// Use mb_strnicmp() because in Turkish comparing the "I" may not work with
// the standard library function.
if (p[0] == '<'
- && (mb_strnicmp((char_u *)p + 1, (char_u *)"SID>", 4) == 0
- || mb_strnicmp((char_u *)p + 1, (char_u *)"SNR>", 4) == 0)) {
+ && (mb_strnicmp(p + 1, "SID>", 4) == 0
+ || mb_strnicmp(p + 1, "SNR>", 4) == 0)) {
return 5;
}
if (p[0] == 's' && p[1] == ':') {
@@ -2666,7 +2638,7 @@ char *get_user_func_name(expand_T *xp, int idx)
return (char *)fp->uf_name; // Prevent overflow.
}
- cat_func_name(IObuff, fp);
+ cat_func_name((char_u *)IObuff, fp);
if (xp->xp_context != EXPAND_USER_FUNC) {
STRCAT(IObuff, "(");
if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) {
@@ -2700,7 +2672,7 @@ void ex_delfunction(exarg_T *eap)
semsg(_(e_trailing_arg), p);
return;
}
- eap->nextcmd = (char *)check_nextcmd(p);
+ eap->nextcmd = check_nextcmd((char *)p);
if (eap->nextcmd != NULL) {
*p = NUL;
}
@@ -2853,7 +2825,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"));
@@ -2889,7 +2861,7 @@ void ex_return(exarg_T *eap)
if (returning) {
eap->nextcmd = NULL;
} else if (eap->nextcmd == NULL) { // no argument
- eap->nextcmd = (char *)check_nextcmd(arg);
+ eap->nextcmd = check_nextcmd((char *)arg);
}
if (eap->skip) {
@@ -3010,7 +2982,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()) {
@@ -3018,7 +2990,7 @@ void ex_call(exarg_T *eap)
semsg(_(e_trailing_arg), arg);
}
} else {
- eap->nextcmd = (char *)check_nextcmd(arg);
+ eap->nextcmd = check_nextcmd((char *)arg);
}
}
@@ -3035,8 +3007,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;
@@ -3086,7 +3058,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
@@ -3105,16 +3077,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 ");
@@ -3123,7 +3095,7 @@ char_u *get_return_cmd(void *rettv)
STRCPY(IObuff + IOSIZE - 4, "...");
}
xfree(tofree);
- return vim_strsave(IObuff);
+ return xstrdup((char *)IObuff);
}
/// Get next function line.
@@ -3134,12 +3106,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) {
@@ -3159,7 +3131,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);
@@ -3169,16 +3141,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)
{
@@ -3190,7 +3162,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;
@@ -3211,9 +3183,9 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
} else {
fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING
? (char_u *)rettv->vval.v_string
- : rettv->vval.v_partial->pt_name;
+ : (char_u *)rettv->vval.v_partial->pt_name;
// Translate "s:func" to the stored function name.
- fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
+ fname = (char_u *)fname_trans_sid((char *)fname, (char *)fname_buf, (char **)&tofree, &error);
fp = find_func(fname);
xfree(tofree);
}
@@ -3227,7 +3199,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
pt->pt_auto = true;
if (rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING) {
// Just a function: Take over the function name and use selfdict.
- pt->pt_name = (char_u *)rettv->vval.v_string;
+ pt->pt_name = rettv->vval.v_string;
} else {
partial_T *ret_pt = rettv->vval.v_partial;
int i;
@@ -3236,8 +3208,8 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
// args. Can't take over name or args, the partial might
// be referenced elsewhere.
if (ret_pt->pt_name != NULL) {
- pt->pt_name = vim_strsave(ret_pt->pt_name);
- func_ref(pt->pt_name);
+ pt->pt_name = xstrdup(ret_pt->pt_name);
+ func_ref((char_u *)pt->pt_name);
} else {
pt->pt_func = ret_pt->pt_func;
func_ptr_ref(pt->pt_func);
@@ -3281,7 +3253,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;
@@ -3559,7 +3531,7 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
}
if (fp_in == NULL) {
- fname = fname_trans_sid(name, fname_buf, &tofree, &error);
+ fname = (char_u *)fname_trans_sid((char *)name, (char *)fname_buf, (char **)&tofree, &error);
fp = find_func(fname);
}
if (fp != NULL) {
@@ -3571,20 +3543,18 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
return abort;
}
-/// Registers a C extension user function.
-char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state)
+/// Registers a luaref as a lambda.
+char_u *register_luafunc(LuaRef ref)
{
char_u *name = get_lambda_name();
ufunc_T *fp = xcalloc(1, offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
fp->uf_refcount = 1;
fp->uf_varargs = true;
- fp->uf_flags = FC_CFUNC;
+ fp->uf_flags = FC_LUAREF;
fp->uf_calls = 0;
fp->uf_script_ctx = current_sctx;
- fp->uf_cb = cb;
- fp->uf_cb_free = cb_free;
- fp->uf_cb_state = state;
+ fp->uf_luaref = ref;
STRCPY(fp->uf_name, name);
hash_add(&func_hashtab, UF2HIKEY(fp));
diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h
index 4b7007aae9..9811f2afb3 100644
--- a/src/nvim/eval/userfunc.h
+++ b/src/nvim/eval/userfunc.h
@@ -9,6 +9,20 @@
#define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name)))
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
+// flags used in uf_flags
+#define FC_ABORT 0x01 // abort function on error
+#define FC_RANGE 0x02 // function accepts range
+#define FC_DICT 0x04 // Dict function, uses "self"
+#define FC_CLOSURE 0x08 // closure, uses outer scope variables
+#define FC_DELETED 0x10 // :delfunction used while uf_refcount > 0
+#define FC_REMOVED 0x20 // function redefined while uf_refcount > 0
+#define FC_SANDBOX 0x40 // function defined in the sandbox
+#define FC_DEAD 0x80 // function kept only for reference to dfunc
+#define FC_EXPORT 0x100 // "export def Func()"
+#define FC_NOARGS 0x200 // no a: variables in lambda
+#define FC_VIM9 0x400 // defined in vim9 script file
+#define FC_LUAREF 0x800 // luaref callback
+
///< Structure used by trans_function_name()
typedef struct {
dict_T *fd_dict; ///< Dictionary used.
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index b38849730a..bf4a9b2ca2 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;
@@ -113,7 +113,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd)
&& STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0) {
mi = marker_indent_len;
}
- if (STRCMP(marker, theline + mi) == 0) {
+ if (strcmp(marker, theline + mi) == 0) {
xfree(theline);
break;
}
@@ -207,7 +207,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const)
list_func_vars(&first);
list_vim_vars(&first);
}
- eap->nextcmd = (char *)check_nextcmd((char_u *)arg);
+ eap->nextcmd = check_nextcmd(arg);
} else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<') {
// HERE document
list_T *l = heredoc_get(eap, expr + 3);
@@ -388,7 +388,7 @@ const char *skip_var_list(const char *arg, int *var_count, int *semicolon)
static const char *skip_var_one(const char *arg)
{
if (*arg == '@' && arg[1] != NUL) {
- return arg + 2;
+ return arg + 1 + utfc_ptr2len(arg + 1);
}
return (char *)find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
@@ -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;
}
@@ -692,10 +691,14 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
return NULL;
}
arg++;
+
+ int regname = utf_ptr2char(arg);
+ int mblen = utf_ptr2len(arg);
+
if (op != NULL && vim_strchr("+-*/%", *op) != NULL) {
semsg(_(e_letwrong), op);
} else if (endchars != NULL
- && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) {
+ && vim_strchr(endchars, *skipwhite(arg + mblen)) == NULL) {
emsg(_(e_letunexp));
} else {
char *s;
@@ -703,17 +706,16 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
char *ptofree = NULL;
const char *p = tv_get_string_chk(tv);
if (p != NULL && op != NULL && *op == '.') {
- s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc);
+ 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);
}
}
if (p != NULL) {
- write_reg_contents(*arg == '@' ? '"' : *arg,
- (const char_u *)p, (ssize_t)STRLEN(p), false);
- arg_end = arg + 1;
+ write_reg_contents(*arg == '@' ? '"' : regname, p, (ssize_t)STRLEN(p), false);
+ arg_end = arg + mblen;
}
xfree(ptofree);
}
@@ -791,6 +793,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;
}
@@ -825,7 +828,7 @@ static void ex_unletlock(exarg_T *eap, char *argstart, int deep, ex_unletlock_ca
arg = skipwhite(name_end);
} while (!ends_excmd(*arg));
- eap->nextcmd = (char *)check_nextcmd((char_u *)arg);
+ eap->nextcmd = check_nextcmd(arg);
}
// TODO(ZyX-I): move to eval/ex_cmds
@@ -1118,7 +1121,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;
@@ -1300,7 +1303,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) {
@@ -1627,7 +1630,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);
}
}
@@ -1702,7 +1705,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));
@@ -1716,19 +1719,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]);
@@ -1737,7 +1740,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;
@@ -1768,19 +1771,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/event/socket.c b/src/nvim/event/socket.c
index 9496a568b9..9ca3dcc276 100644
--- a/src/nvim/event/socket.c
+++ b/src/nvim/event/socket.c
@@ -125,7 +125,7 @@ int socket_watcher_start(SocketWatcher *watcher, int backlog, socket_cb cb)
// Libuv converts ENOENT to EACCES for Windows compatibility, but if
// the parent directory does not exist, ENOENT would be more accurate.
*path_tail(watcher->addr) = NUL;
- if (!os_path_exists((char_u *)watcher->addr)) {
+ if (!os_path_exists(watcher->addr)) {
result = UV_ENOENT;
}
}
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 06a372bb93..96bef4902c 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1,9 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * ex_cmds.c: some functions for command line commands
- */
+// ex_cmds.c: some functions for command line commands
#include <assert.h>
#include <float.h>
@@ -249,11 +247,9 @@ void ex_align(exarg_T *eap)
indent = width;
}
} else {
- /*
- * if 'textwidth' set, use it
- * else if 'wrapmargin' set, use it
- * if invalid value, use 80
- */
+ // if 'textwidth' set, use it
+ // else if 'wrapmargin' set, use it
+ // if invalid value, use 80
if (width <= 0) {
width = (int)curbuf->b_p_tw;
}
@@ -274,7 +270,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();
@@ -287,18 +283,14 @@ void ex_align(exarg_T *eap)
} else {
new_indent = width - len; // right align
- /*
- * Make sure that embedded TABs don't make the text go too far
- * to the right.
- */
+ // Make sure that embedded TABs don't make the text go too far
+ // to the right.
if (has_tab) {
while (new_indent > 0) {
(void)set_indent(new_indent, 0);
if (linelen(NULL) <= width) {
- /*
- * Now try to move the line as much as possible to
- * the right. Stop when it moves too far.
- */
+ // Now try to move the line as much as possible to
+ // the right. Stop when it moves too far.
do {
(void)set_indent(++new_indent, 0);
} while (linelen(NULL) <= width);
@@ -330,7 +322,7 @@ static int linelen(int *has_tab)
// Get the line. If it's empty bail out early (could be the empty string
// for an unloaded buffer).
- line = (char *)get_cursor_line_ptr();
+ line = get_cursor_line_ptr();
if (*line == NUL) {
return 0;
}
@@ -387,7 +379,7 @@ static int string_compare(const void *s1, const void *s2) FUNC_ATTR_NONNULL_ALL
if (sort_lc) {
return strcoll((char *)s1, (char *)s2);
}
- return sort_ic ? STRICMP(s1, s2) : STRCMP(s1, s2);
+ return sort_ic ? STRICMP(s1, s2) : strcmp(s1, s2);
}
static int sort_compare(const void *s1, const void *s2)
@@ -404,7 +396,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
@@ -509,11 +501,11 @@ void ex_sort(exarg_T *eap)
} else if (*p == '"') {
// comment start
break;
- } else if (check_nextcmd((char_u *)p) != NULL) {
- eap->nextcmd = (char *)check_nextcmd((char_u *)p);
+ } else if (check_nextcmd(p) != NULL) {
+ eap->nextcmd = check_nextcmd(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;
@@ -557,7 +549,7 @@ void ex_sort(exarg_T *eap)
// matching and number conversion only has to be done once per line.
// Also get the longest line length for allocating "sortbuf".
for (lnum = eap->line1; lnum <= eap->line2; lnum++) {
- s = (char *)ml_get(lnum);
+ s = ml_get(lnum);
len = (int)STRLEN(s);
if (maxlen < len) {
maxlen = len;
@@ -567,10 +559,10 @@ void ex_sort(exarg_T *eap)
end_col = len;
if (regmatch.regprog != NULL && vim_regexec(&regmatch, s, 0)) {
if (sort_rx) {
- start_col = (colnr_T)(regmatch.startp[0] - (char_u *)s);
- end_col = (colnr_T)(regmatch.endp[0] - (char_u *)s);
+ start_col = (colnr_T)(regmatch.startp[0] - s);
+ end_col = (colnr_T)(regmatch.endp[0] - s);
} else {
- start_col = (colnr_T)(regmatch.endp[0] - (char_u *)s);
+ start_col = (colnr_T)(regmatch.endp[0] - s);
}
} else if (regmatch.regprog != NULL) {
end_col = 0;
@@ -586,11 +578,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
@@ -601,7 +593,7 @@ void ex_sort(exarg_T *eap)
nrs[lnum - eap->line1].st_u.num.value = 0;
} else {
nrs[lnum - eap->line1].st_u.num.is_number = true;
- vim_str2nr((char_u *)s, NULL, NULL, sort_what,
+ vim_str2nr(s, NULL, NULL, sort_what,
&nrs[lnum - eap->line1].st_u.num.value, NULL, 0, false);
}
} else {
@@ -658,7 +650,7 @@ void ex_sort(exarg_T *eap)
change_occurred = true;
}
- s = (char *)ml_get(get_lnum);
+ s = ml_get(get_lnum);
size_t bytelen = STRLEN(s) + 1; // include EOL in bytelen
old_count += (bcount_t)bytelen;
if (!unique || i == 0 || string_compare(s, sortbuf1) != 0) {
@@ -678,7 +670,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 +735,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) == ',') {
@@ -760,7 +752,7 @@ void ex_retab(exarg_T *eap)
new_ts_str = xstrnsave(new_ts_str, (size_t)(eap->arg - new_ts_str));
}
for (lnum = eap->line1; !got_int && lnum <= eap->line2; lnum++) {
- ptr = (char *)ml_get(lnum);
+ ptr = ml_get(lnum);
col = 0;
vcol = 0;
did_undo = false;
@@ -841,7 +833,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 +859,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);
@@ -933,15 +925,13 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
num_lines = line2 - line1 + 1;
- /*
- * First we copy the old text to its new location -- webb
- * Also copy the flag that ":global" command uses.
- */
+ // First we copy the old text to its new location -- webb
+ // Also copy the flag that ":global" command uses.
if (u_save(dest, dest + 1) == FAIL) {
return FAIL;
}
for (extra = 0, l = line1; l <= line2; l++) {
- str = (char *)vim_strsave(ml_get(l + extra));
+ str = xstrdup(ml_get(l + extra));
ml_append(dest + l - line1, str, (colnr_T)0, false);
xfree(str);
if (dest < line1) {
@@ -949,21 +939,19 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
}
}
- /*
- * Now we must be careful adjusting our marks so that we don't overlap our
- * mark_adjust() calls.
- *
- * We adjust the marks within the old text so that they refer to the
- * last lines of the file (temporarily), because we know no other marks
- * will be set there since these line numbers did not exist until we added
- * our new lines.
- *
- * Then we adjust the marks on lines between the old and new text positions
- * (either forwards or backwards).
- *
- * And Finally we adjust the marks we put at the end of the file back to
- * their final destination at the new text position -- webb
- */
+ // Now we must be careful adjusting our marks so that we don't overlap our
+ // mark_adjust() calls.
+ //
+ // We adjust the marks within the old text so that they refer to the
+ // last lines of the file (temporarily), because we know no other marks
+ // will be set there since these line numbers did not exist until we added
+ // our new lines.
+ //
+ // Then we adjust the marks on lines between the old and new text positions
+ // (either forwards or backwards).
+ //
+ // And Finally we adjust the marks we put at the end of the file back to
+ // their final destination at the new text position -- webb
last_line = curbuf->b_ml.ml_line_count;
mark_adjust_nofold(line1, line2, last_line - line2, 0L, kExtmarkNOOP);
@@ -1011,9 +999,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
// send update regarding the new lines that were added
buf_updates_send_changes(curbuf, dest + 1, num_lines, 0);
- /*
- * Now we delete the original text -- webb
- */
+ // Now we delete the original text -- webb
if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL) {
return FAIL;
}
@@ -1030,9 +1016,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
dest + line_off, 0, dest_byte + byte_off,
kExtmarkUndo);
- /*
- * Leave the cursor on the last of the moved lines.
- */
+ // Leave the cursor on the last of the moved lines.
if (dest >= line1) {
curwin->w_cursor.lnum = dest;
} else {
@@ -1069,26 +1053,24 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
}
- /*
- * there are three situations:
- * 1. destination is above line1
- * 2. destination is between line1 and line2
- * 3. destination is below line2
- *
- * n = destination (when starting)
- * curwin->w_cursor.lnum = destination (while copying)
- * line1 = start of source (while copying)
- * line2 = end of source (while copying)
- */
+ // there are three situations:
+ // 1. destination is above line1
+ // 2. destination is between line1 and line2
+ // 3. destination is below line2
+ //
+ // n = destination (when starting)
+ // curwin->w_cursor.lnum = destination (while copying)
+ // line1 = start of source (while copying)
+ // line2 = end of source (while copying)
if (u_save(n, n + 1) == FAIL) {
return;
}
curwin->w_cursor.lnum = n;
while (line1 <= line2) {
- // need to use vim_strsave() because the line will be unlocked within
+ // need to use xstrdup() because the line will be unlocked within
// ml_append()
- p = (char *)vim_strsave(ml_get(line1));
+ p = xstrdup(ml_get(line1));
ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, false);
xfree(p);
@@ -1103,7 +1085,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,15 +1132,13 @@ 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;
}
- /*
- * Try to find an embedded bang, like in :!<cmd> ! [args]
- * (:!! is indicated by the 'forceit' variable)
- */
+ // Try to find an embedded bang, like in :!<cmd> ! [args]
+ // (:!! is indicated by the 'forceit' variable)
bool ins_prevcmd = forceit;
trailarg = arg;
do {
@@ -1187,10 +1167,8 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
xfree(newcmd);
newcmd = t;
- /*
- * Scan the rest of the argument for '!', which is replaced by the
- * previous command. "\!" is replaced by "!" (this is vi compatible).
- */
+ // Scan the rest of the argument for '!', which is replaced by the
+ // previous command. "\!" is replaced by "!" (this is vi compatible).
trailarg = NULL;
while (*p) {
if (*p == '!') {
@@ -1221,9 +1199,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out
AppendToRedobuff("\n");
bangredo = false;
}
- /*
- * Add quotes around the command, for shells that need them.
- */
+ // Add quotes around the command, for shells that need them.
if (*p_shq != NUL) {
newcmd = xmalloc(STRLEN(prevcmd) + 2 * STRLEN(p_shq) + 1);
STRCPY(newcmd, p_shq);
@@ -1298,18 +1274,16 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
changed_line_abv_curs();
invalidate_botline();
- /*
- * When using temp files:
- * 1. * Form temp file names
- * 2. * Write the lines to a temp file
- * 3. Run the filter command on the temp file
- * 4. * Read the output of the command into the buffer
- * 5. * Delete the original lines to be filtered
- * 6. * Remove the temp files
- *
- * When writing the input with a pipe or when catching the output with a
- * pipe only need to do 3.
- */
+ // When using temp files:
+ // 1. * Form temp file names
+ // 2. * Write the lines to a temp file
+ // 3. Run the filter command on the temp file
+ // 4. * Read the output of the command into the buffer
+ // 5. * Delete the original lines to be filtered
+ // 6. * Remove the temp files
+ //
+ // When writing the input with a pipe or when catching the output with a
+ // pipe only need to do 3.
if (do_out) {
shell_flags |= kShellOptDoOut;
@@ -1331,23 +1305,22 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
curbuf->b_op_start.lnum = line1;
curbuf->b_op_end.lnum = line2;
curwin->w_cursor.lnum = line2;
- } else if ((do_in && (itmp = (char *)vim_tempname()) == NULL)
- || (do_out && (otmp = (char *)vim_tempname()) == NULL)) {
+ } else if ((do_in && (itmp = vim_tempname()) == NULL)
+ || (do_out && (otmp = vim_tempname()) == NULL)) {
emsg(_(e_notmp));
goto filterend;
}
- /*
- * The writing and reading of temp files will not be shown.
- * Vi also doesn't do this and the messages are not very informative.
- */
+ // The writing and reading of temp files will not be shown.
+ // Vi also doesn't do this and the messages are not very informative.
no_wait_return++; // don't call wait_return() while busy
if (itmp != NULL && buf_write(curbuf, itmp, NULL, line1, line2, eap,
false, false, false, true) == FAIL) {
msg_putchar('\n'); // Keep message from buf_write().
no_wait_return--;
if (!aborting()) {
- 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 +1341,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 +1349,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) {
@@ -1427,10 +1400,8 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
}
}
- /*
- * Put cursor on first filtered line for ":range!cmd".
- * Adjust '[ and '] (set by buf_write()).
- */
+ // Put cursor on first filtered line for ":range!cmd".
+ // Adjust '[ and '] (set by buf_write()).
curwin->w_cursor.lnum = line1;
del_lines(linecount, true);
curbuf->b_op_start.lnum -= linecount; // adjust '[
@@ -1439,9 +1410,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
// for next write
foldUpdate(curwin, curbuf->b_op_start.lnum, curbuf->b_op_end.lnum);
} else {
- /*
- * Put cursor on last new line for ":r !cmd".
- */
+ // Put cursor on last new line for ":r !cmd".
linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
}
@@ -1503,10 +1472,8 @@ void do_shell(char *cmd, int flags)
return;
}
- /*
- * For autocommands we want to get the output on the current screen, to
- * avoid having to type return below.
- */
+ // For autocommands we want to get the output on the current screen, to
+ // avoid having to type return below.
msg_putchar('\r'); // put cursor at start of line
msg_putchar('\n'); // may shift screen one line up
@@ -1568,12 +1535,12 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
{
bool is_fish_shell =
#if defined(UNIX)
- STRNCMP(invocation_path_tail(p_sh, NULL), "fish", 4) == 0;
+ STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "fish", 4) == 0;
#else
false;
#endif
- bool is_pwsh = STRNCMP(invocation_path_tail(p_sh, NULL), "pwsh", 4) == 0
- || STRNCMP(invocation_path_tail(p_sh, NULL), "powershell", 10) == 0;
+ bool is_pwsh = STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "pwsh", 4) == 0
+ || STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "powershell", 10) == 0;
size_t len = STRLEN(cmd) + 1; // At least enough space for cmd + NULL.
@@ -1656,7 +1623,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;
}
@@ -1714,7 +1681,7 @@ void print_line(linenr_T lnum, int use_number, int list)
}
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) {
@@ -1739,13 +1706,11 @@ int rename_buffer(char *new_fname)
if (aborting()) { // autocmds may abort script processing
return FAIL;
}
- /*
- * The name of the current buffer will be changed.
- * A new (unlisted) buffer entry needs to be made to hold the old file
- * name, which will become the alternate file name.
- * But don't set the alternate file name if the buffer didn't have a
- * name.
- */
+ // The name of the current buffer will be changed.
+ // A new (unlisted) buffer entry needs to be made to hold the old file
+ // name, which will become the alternate file name.
+ // But don't set the alternate file name if the buffer didn't have a
+ // name.
fname = curbuf->b_ffname;
sfname = curbuf->b_sfname;
xfname = curbuf->b_fname;
@@ -1822,7 +1787,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 +1812,7 @@ int do_write(exarg_T *eap)
emsg(_(e_argreq));
goto theend;
}
- other = FALSE;
+ other = false;
} else {
fname = ffname;
free_fname = fix_fname(ffname);
@@ -1859,9 +1824,7 @@ int do_write(exarg_T *eap)
other = otherfile(ffname);
}
- /*
- * If we have a new file, put its name in the list of alternate file names.
- */
+ // If we have a new file, put its name in the list of alternate file names.
if (other) {
if (vim_strchr(p_cpo, CPO_ALTWRITE) != NULL
|| eap->cmdidx == CMD_saveas) {
@@ -1880,8 +1843,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;
}
@@ -1897,10 +1859,10 @@ int do_write(exarg_T *eap)
&& !p_wa) {
if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
if (vim_dialog_yesno(VIM_QUESTION, NULL,
- (char_u *)_("Write partial file?"), 2) != VIM_YES) {
+ _("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 +1899,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 +1928,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 +1958,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)) {
+ && os_path_exists(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;
}
@@ -2015,10 +1982,10 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
char buff[DIALOG_MSG_SIZE];
dialog_msg((char *)buff, _("Overwrite existing file \"%s\"?"), fname);
- if (vim_dialog_yesno(VIM_QUESTION, NULL, (char_u *)buff, 2) != VIM_YES) {
+ if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES) {
return FAIL;
}
- eap->forceit = TRUE;
+ eap->forceit = true;
} else {
emsg(_(e_exists));
return FAIL;
@@ -2041,24 +2008,24 @@ 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);
xfree(dir);
- if (os_path_exists((char_u *)swapname)) {
+ if (os_path_exists(swapname)) {
if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
char buff[DIALOG_MSG_SIZE];
dialog_msg((char *)buff,
_("Swap file \"%s\" exists, overwrite anyway?"),
swapname);
- if (vim_dialog_yesno(VIM_QUESTION, NULL, (char_u *)buff, 2)
+ if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2)
!= VIM_YES) {
xfree(swapname);
return FAIL;
}
- eap->forceit = TRUE;
+ eap->forceit = true;
} else {
semsg(_("E768: Swap file exists: %s (:silent! overrides)"),
swapname);
@@ -2108,13 +2075,11 @@ void do_wqall(exarg_T *eap)
} else if (!bufIsChanged(buf) || bt_dontwrite(buf)) {
continue;
}
- /*
- * Check if there is a reason the buffer cannot be written:
- * 1. if the 'write' option is set
- * 2. if there is no file name (even after browsing)
- * 3. if the 'readonly' is set (even after a dialog)
- * 4. if overwriting is allowed (even after a dialog)
- */
+ // Check if there is a reason the buffer cannot be written:
+ // 1. if the 'write' option is set
+ // 2. if there is no file name (even after browsing)
+ // 3. if the 'readonly' is set (even after a dialog)
+ // 4. if overwriting is allowed (even after a dialog)
if (not_writing()) {
error++;
break;
@@ -2159,14 +2124,14 @@ 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)
{
// Handle a file being readonly when the 'readonly' option is set or when
// the file exists and permissions are read-only.
if (!*forceit && (buf->b_p_ro
- || (os_path_exists((char_u *)buf->b_ffname)
+ || (os_path_exists(buf->b_ffname)
&& !os_file_is_writable(buf->b_ffname)))) {
if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && buf->b_fname != NULL) {
char buff[DIALOG_MSG_SIZE];
@@ -2182,12 +2147,12 @@ static int check_readonly(int *forceit, buf_T *buf)
buf->b_fname);
}
- if (vim_dialog_yesno(VIM_QUESTION, NULL, (char_u *)buff, 2) == VIM_YES) {
+ if (vim_dialog_yesno(VIM_QUESTION, NULL, 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 +2160,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 +2257,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 +2275,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 +2351,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))))
@@ -2400,10 +2365,8 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
goto theend;
}
- /*
- * End Visual mode before switching to another buffer, so the text can be
- * copied into the GUI selection buffer.
- */
+ // End Visual mode before switching to another buffer, so the text can be
+ // copied into the GUI selection buffer.
reset_VIsual();
if ((command != NULL || newlnum > (linenr_T)0)
@@ -2421,10 +2384,8 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
xfree(p);
}
- /*
- * If we are starting to edit another file, open a (new) buffer.
- * Otherwise we re-use the current buffer.
- */
+ // If we are starting to edit another file, open a (new) buffer.
+ // Otherwise we re-use the current buffer.
if (other_file) {
const int prev_alt_fnum = curwin->w_alt_fnum;
@@ -2502,12 +2463,10 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
solcol = pos->col;
}
- /*
- * 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 current buffer was empty and has no file name, curbuf
- * is returned by buflist_new(), nothing to do here.
- */
+ // 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 current buffer was empty and has no file name, curbuf
+ // is returned by buflist_new(), nothing to do here.
if (buf != curbuf) {
const int save_cmdwin_type = cmdwin_type;
@@ -2601,11 +2560,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 +2600,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
@@ -2658,13 +2617,11 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// highlighting to work in the other file.
did_filetype = false;
- /*
- * 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)
- */
+ // 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)
if (!other_file && !oldbuf) { // re-use the buffer
set_last_cursor(curwin); // may set b_last_cursor
if (newlnum == ECMD_LAST || newlnum == ECMD_LASTL) {
@@ -2673,7 +2630,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
}
buf = curbuf;
if (buf->b_fname != NULL) {
- new_name = (char *)vim_strsave((char_u *)buf->b_fname);
+ new_name = xstrdup(buf->b_fname);
} else {
new_name = NULL;
}
@@ -2723,9 +2680,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
curbuf->b_op_end.lnum = 0;
}
- /*
- * If we get here we are sure to start editing
- */
+ // If we get here we are sure to start editing
// Assume success now
retval = OK;
@@ -2736,17 +2691,13 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
curbuf->b_flags &= ~BF_NOTEDITED;
}
- /*
- * Check if we are editing the w_arg_idx file in the argument list.
- */
+ // Check if we are editing the w_arg_idx file in the argument list.
check_arg_idx(curwin);
if (!auto_buf) {
- /*
- * Set cursor and init window before reading the file and executing
- * autocommands. This allows for the autocommands to position the
- * cursor.
- */
+ // Set cursor and init window before reading the file and executing
+ // autocommands. This allows for the autocommands to position the
+ // cursor.
curwin_init();
// It's possible that all lines in the buffer changed. Need to update
@@ -2760,19 +2711,15 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// Change directories when the 'acd' option is set.
do_autochdir();
- /*
- * Careful: open_buffer() and apply_autocmds() may change the current
- * buffer and window.
- */
+ // Careful: open_buffer() and apply_autocmds() may change the current
+ // buffer and window.
orig_pos = curwin->w_cursor;
topline = curwin->w_topline;
if (!oldbuf) { // need to read the file
swap_exists_action = SEA_DIALOG;
curbuf->b_flags |= BF_CHECK_RO; // set/reset 'ro' flag
- /*
- * Open the buffer and read the file.
- */
+ // Open the buffer and read the file.
if (flags & ECMD_NOWINENTER) {
readfile_flags |= READ_NOWINENTER;
}
@@ -2790,7 +2737,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,
@@ -2803,7 +2750,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// keep it. Also when it moves within a line. But not when it moves
// to the first non-blank.
if (!equalpos(curwin->w_cursor, orig_pos)) {
- const char *text = (char *)get_cursor_line_ptr();
+ const char *text = get_cursor_line_ptr();
if (curwin->w_cursor.lnum != orig_pos.lnum
|| curwin->w_cursor.col != (int)(skipwhite(text) - text)) {
@@ -2848,7 +2795,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);
}
@@ -2863,10 +2810,8 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// Check if cursors in other windows on the same buffer are still valid
check_lnums(false);
- /*
- * Did not read the file, need to show some info about the file.
- * Do this after setting the cursor.
- */
+ // Did not read the file, need to show some info about the file.
+ // Do this after setting the cursor.
if (oldbuf
&& !auto_buf) {
int msg_scroll_save = msg_scroll;
@@ -2874,7 +2819,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 +2855,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 +2963,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 +3043,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;
}
@@ -3313,7 +3258,7 @@ static bool sub_joining_lines(exarg_T *eap, char *pat, char *sub, char *cmd, boo
// TODO(vim): find a generic solution to make line-joining operations more
// efficient, avoid allocating a string that grows in size.
if (pat != NULL
- && STRCMP(pat, "\\n") == 0
+ && strcmp(pat, "\\n") == 0
&& *sub == NUL
&& (*cmd == NUL || (cmd[1] == NUL
&& (*cmd == 'g'
@@ -3346,10 +3291,10 @@ static bool sub_joining_lines(exarg_T *eap, char *pat, char *sub, char *cmd, boo
if (save) {
if ((cmdmod.cmod_flags & CMOD_KEEPPATTERNS) == 0) {
- save_re_pat(RE_SUBST, (char_u *)pat, p_magic);
+ save_re_pat(RE_SUBST, pat, p_magic);
}
// put pattern in history
- add_to_history(HIST_SEARCH, (char_u *)pat, true, NUL);
+ add_to_history(HIST_SEARCH, pat, true, NUL);
}
return true;
@@ -3547,17 +3492,15 @@ 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;
}
}
- /*
- * Small incompatibility: vi sees '\n' as end of the command, but in
- * Vim we want to use '\n' to find/substitute a NUL.
- */
+ // Small incompatibility: vi sees '\n' as end of the command, but in
+ // Vim we want to use '\n' to find/substitute a NUL.
sub = cmd; // remember the start of the substitution
while (cmd[0]) {
@@ -3615,12 +3558,10 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
}
}
- /*
- * check for trailing command or garbage
- */
+ // check for trailing command or garbage
cmd = skipwhite(cmd);
if (*cmd && *cmd != '"') { // if not end-of-line or comment
- eap->nextcmd = (char *)check_nextcmd((char_u *)cmd);
+ eap->nextcmd = check_nextcmd(cmd);
if (eap->nextcmd == NULL) {
semsg(_(e_trailing_arg), cmd);
return 0;
@@ -3667,7 +3608,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
sub = xstrdup(sub);
sub_copy = sub;
} else {
- char *newsub = (char *)regtilde((char_u *)sub, p_magic, cmdpreview);
+ char *newsub = regtilde(sub, p_magic, cmdpreview);
if (newsub != sub) {
// newsub was allocated, free it later.
sub_copy = newsub;
@@ -3706,50 +3647,48 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
bool skip_match = false;
linenr_T sub_firstlnum; // nr of first sub line
- /*
- * The new text is build up step by step, to avoid too much
- * copying. There are these pieces:
- * sub_firstline The old text, unmodified.
- * copycol Column in the old text where we started
- * looking for a match; from here old text still
- * needs to be copied to the new text.
- * matchcol Column number of the old text where to look
- * for the next match. It's just after the
- * previous match or one further.
- * prev_matchcol Column just after the previous match (if any).
- * Mostly equal to matchcol, except for the first
- * match and after skipping an empty match.
- * regmatch.*pos Where the pattern matched in the old text.
- * new_start The new text, all that has been produced so
- * far.
- * new_end The new text, where to append new text.
- *
- * lnum The line number where we found the start of
- * the match. Can be below the line we searched
- * when there is a \n before a \zs in the
- * pattern.
- * sub_firstlnum The line number in the buffer where to look
- * for a match. Can be different from "lnum"
- * when the pattern or substitute string contains
- * line breaks.
- *
- * Special situations:
- * - When the substitute string contains a line break, the part up
- * to the line break is inserted in the text, but the copy of
- * the original line is kept. "sub_firstlnum" is adjusted for
- * the inserted lines.
- * - When the matched pattern contains a line break, the old line
- * is taken from the line at the end of the pattern. The lines
- * in the match are deleted later, "sub_firstlnum" is adjusted
- * accordingly.
- *
- * The new text is built up in new_start[]. It has some extra
- * room to avoid using xmalloc()/free() too often.
- *
- * Make a copy of the old line, so it won't be taken away when
- * updating the screen or handling a multi-line match. The "old_"
- * pointers point into this copy.
- */
+ // The new text is build up step by step, to avoid too much
+ // copying. There are these pieces:
+ // sub_firstline The old text, unmodified.
+ // copycol Column in the old text where we started
+ // looking for a match; from here old text still
+ // needs to be copied to the new text.
+ // matchcol Column number of the old text where to look
+ // for the next match. It's just after the
+ // previous match or one further.
+ // prev_matchcol Column just after the previous match (if any).
+ // Mostly equal to matchcol, except for the first
+ // match and after skipping an empty match.
+ // regmatch.*pos Where the pattern matched in the old text.
+ // new_start The new text, all that has been produced so
+ // far.
+ // new_end The new text, where to append new text.
+ //
+ // lnum The line number where we found the start of
+ // the match. Can be below the line we searched
+ // when there is a \n before a \zs in the
+ // pattern.
+ // sub_firstlnum The line number in the buffer where to look
+ // for a match. Can be different from "lnum"
+ // when the pattern or substitute string contains
+ // line breaks.
+ //
+ // Special situations:
+ // - When the substitute string contains a line break, the part up
+ // to the line break is inserted in the text, but the copy of
+ // the original line is kept. "sub_firstlnum" is adjusted for
+ // the inserted lines.
+ // - When the matched pattern contains a line break, the old line
+ // is taken from the line at the end of the pattern. The lines
+ // in the match are deleted later, "sub_firstlnum" is adjusted
+ // accordingly.
+ //
+ // The new text is built up in new_start[]. It has some extra
+ // room to avoid using xmalloc()/free() too often.
+ //
+ // Make a copy of the old line, so it won't be taken away when
+ // updating the screen or handling a multi-line match. The "old_"
+ // pointers point into this copy.
sub_firstlnum = lnum;
copycol = 0;
matchcol = 0;
@@ -3760,14 +3699,12 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
got_match = true;
}
- /*
- * Loop until nothing more to replace in this line.
- * 1. Handle match with empty string.
- * 2. If subflags.do_ask is set, ask for confirmation.
- * 3. substitute the string.
- * 4. if subflags.do_all is set, find next match
- * 5. break if there isn't another match in this line
- */
+ // Loop until nothing more to replace in this line.
+ // 1. Handle match with empty string.
+ // 2. If subflags.do_ask is set, ask for confirmation.
+ // 3. substitute the string.
+ // 4. if subflags.do_all is set, find next match
+ // 5. break if there isn't another match in this line
for (;;) {
SubResult current_match = {
.start = { 0, 0 },
@@ -3798,19 +3735,17 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
break;
}
if (sub_firstline == NULL) {
- sub_firstline = (char *)vim_strsave(ml_get(sub_firstlnum));
+ sub_firstline = xstrdup(ml_get(sub_firstlnum));
}
// 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
- * match. This reproduces the strange vi behaviour.
- * This also catches endless loops.
- */
+ // 1. Match empty string does not count, except for first
+ // match. This reproduces the strange vi behaviour.
+ // This also catches endless loops.
if (matchcol == prev_matchcol
&& regmatch.endpos[0].lnum == 0
&& matchcol == regmatch.endpos[0].col) {
@@ -3875,9 +3810,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
no_u_sync++;
}
- /*
- * Loop until 'y', 'n', 'q', CTRL-E or CTRL-Y typed.
- */
+ // Loop until 'y', 'n', 'q', CTRL-E or CTRL-Y typed.
while (subflags.do_ask) {
if (exmode_active) {
char *prompt;
@@ -3939,9 +3872,8 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// really update the line, it would change
// 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);
+ orig_line = xstrdup(ml_get(lnum));
+ 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 +3887,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) {
@@ -4068,7 +4000,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
if (nmatch > 1) { \
sub_firstlnum += (linenr_T)nmatch - 1; \
xfree(sub_firstline); \
- sub_firstline = (char *)vim_strsave(ml_get(sub_firstlnum)); \
+ sub_firstline = xstrdup(ml_get(sub_firstlnum)); \
/* When going beyond the last line, stop substituting. */ \
if (sub_firstlnum <= line2) { \
do_again = true; \
@@ -4144,7 +4076,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
if (nmatch == 1) {
p1 = sub_firstline;
} else {
- p1 = (char *)ml_get(sub_firstlnum + (linenr_T)nmatch - 1);
+ p1 = ml_get(sub_firstlnum + (linenr_T)nmatch - 1);
nmatch_tl += nmatch - 1;
}
size_t copy_len = (size_t)(regmatch.startpos[0].col - copycol);
@@ -4262,15 +4194,13 @@ skip:
&& !re_multiline(regmatch.regprog)));
nmatch = -1;
- /*
- * Replace the line in the buffer when needed. This is
- * skipped when there are more matches.
- * The check for nmatch_tl is needed for when multi-line
- * matching must replace the lines before trying to do another
- * match, otherwise "\@<=" won't work.
- * When the match starts below where we start searching also
- * need to replace the line first (using \zs after \n).
- */
+ // Replace the line in the buffer when needed. This is
+ // skipped when there are more matches.
+ // The check for nmatch_tl is needed for when multi-line
+ // matching must replace the lines before trying to do another
+ // match, otherwise "\@<=" won't work.
+ // When the match starts below where we start searching also
+ // need to replace the line first (using \zs after \n).
if (lastone
|| nmatch_tl > 0
|| (nmatch = vim_regexec_multi(&regmatch, curwin,
@@ -4278,13 +4208,11 @@ skip:
matchcol, NULL, NULL)) == 0
|| regmatch.startpos[0].lnum > 0) {
if (new_start != NULL) {
- /*
- * Copy the rest of the line, that didn't match.
- * "matchcol" has to be adjusted, we use the end of
- * the line as reference, because the substitute may
- * have changed the number of characters. Same for
- * "prev_matchcol".
- */
+ // Copy the rest of the line, that didn't match.
+ // "matchcol" has to be adjusted, we use the end of
+ // the line as reference, because the substitute may
+ // have changed the number of characters. Same for
+ // "prev_matchcol".
STRCAT(new_start, sub_firstline + copycol);
matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol;
prev_matchcol = (colnr_T)STRLEN(sub_firstline)
@@ -4296,12 +4224,10 @@ skip:
ml_replace(lnum, new_start, true);
if (nmatch_tl > 0) {
- /*
- * Matched lines have now been substituted and are
- * useless, delete them. The part after the match
- * has been appended to new_start, we don't need
- * it in the buffer.
- */
+ // Matched lines have now been substituted and are
+ // useless, delete them. The part after the match
+ // has been appended to new_start, we don't need
+ // it in the buffer.
lnum++;
if (u_savedel(lnum, nmatch_tl) != OK) {
break;
@@ -4344,9 +4270,7 @@ skip:
sub_firstlnum, matchcol, NULL, NULL);
}
- /*
- * 5. break if there isn't another match in this line
- */
+ // 5. break if there isn't another match in this line
if (nmatch <= 0) {
// If the match found didn't start where we were
// searching, do the next search in the line where we
@@ -4509,12 +4433,10 @@ skip:
/// @return true if a message was given.
bool do_sub_msg(bool count_only)
{
- /*
- * Only report substitutions when:
- * - more than 'report' substitutions
- * - command was typed by user, or number of changed lines > 'report'
- * - giving messages is not disabled by 'lazyredraw'
- */
+ // Only report substitutions when:
+ // - more than 'report' substitutions
+ // - command was typed by user, or number of changed lines > 'report'
+ // - giving messages is not disabled by 'lazyredraw'
if (((sub_nsubs > p_report && (KeyTyped || sub_nlines > 1 || p_report < 1))
|| count_only)
&& messaging()) {
@@ -4605,11 +4527,9 @@ void ex_global(exarg_T *eap)
cmd = eap->arg;
which_pat = RE_LAST; // default: use last used regexp
- /*
- * undocumented vi feature:
- * "\/" and "\?": use previous search pattern.
- * "\&": use previous substitute pattern.
- */
+ // undocumented vi feature:
+ // "\/" and "\?": use previous search pattern.
+ // "\&": use previous substitute pattern.
if (*cmd == '\\') {
cmd++;
if (vim_strchr("/?&", *cmd) == NULL) {
@@ -4632,7 +4552,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
}
@@ -4748,9 +4668,7 @@ void free_old_sub(void)
/// @return true when it was created.
bool prepare_tagpreview(bool undo_sync)
{
- /*
- * If there is already a preview window open, use that one.
- */
+ // If there is already a preview window open, use that one.
if (!curwin->w_p_pvw) {
bool found_win = false;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
@@ -4761,17 +4679,14 @@ bool prepare_tagpreview(bool undo_sync)
}
}
if (!found_win) {
- /*
- * There is no preview window open yet. Create one.
- */
+ // There is no preview window open yet. Create one.
if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0)
== 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 +4704,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.
@@ -4867,7 +4782,7 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
if (next_linenr == orig_buf->b_ml.ml_line_count + 1) {
line = "";
} else {
- line = (char *)ml_get_buf(orig_buf, next_linenr, false);
+ line = ml_get_buf(orig_buf, next_linenr, false);
line_size = strlen(line) + (size_t)col_width + 1;
// Reallocate if line not long enough
@@ -4940,7 +4855,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 +4865,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,13 +4910,12 @@ 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)));
msg_clr_eos();
msg_putchar('\n');
- ui_flush(); // output one line at a time
os_breakcheck();
}
});
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 4bed1e94b9..04b8832428 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -1141,6 +1141,12 @@ module.cmds = {
func='ex_history',
},
{
+ command='horizontal',
+ flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type='ADDR_NONE',
+ func='ex_wrongmodifier',
+ },
+ {
command='insert',
flags=bit.bor(BANG, RANGE, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
addr_type='ADDR_LINES',
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 54315a6417..e551cbee0b 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
@@ -204,9 +200,9 @@ void dialog_changed(buf_T *buf, bool checkall)
dialog_msg((char *)buff, _("Save changes to \"%s\"?"), buf->b_fname);
if (checkall) {
- ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, (char_u *)buff, 1);
+ ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1);
} else {
- ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, (char_u *)buff, 1);
+ ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
}
if (ret == VIM_YES) {
@@ -256,7 +252,7 @@ bool dialog_close_terminal(buf_T *buf)
dialog_msg(buff, _("Close \"%s\"?"),
(buf->b_fname != NULL) ? buf->b_fname : "?");
- int ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, (char_u *)buff, 1);
+ int ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
return ret == VIM_YES;
}
@@ -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..2045f5d28e 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 = xstrdup(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))
@@ -631,9 +642,8 @@ 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,
+ if (breakpoint != NULL && lines_ga.ga_len > current_line) {
+ *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;
@@ -775,7 +785,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
vim_snprintf((char *)IObuff, IOSIZE,
_("E605: Exception not caught: %s"),
current_exception->value);
- p = (char *)vim_strsave(IObuff);
+ p = xstrdup((char *)IObuff);
break;
case ET_ERROR:
messages = current_exception->messages;
@@ -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;
@@ -1290,7 +1300,7 @@ static void parse_register(exarg_T *eap)
// for '=' register: accept the rest of the line as an expression
if (eap->arg[-1] == '=' && eap->arg[0] != NUL) {
if (!eap->skip) {
- set_expr_line(vim_strsave((char_u *)eap->arg));
+ set_expr_line(xstrdup(eap->arg));
}
eap->arg += STRLEN(eap->arg);
}
@@ -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
@@ -1738,6 +1757,7 @@ static bool skip_cmd(const exarg_T *eap)
case CMD_filter:
case CMD_help:
case CMD_hide:
+ case CMD_horizontal:
case CMD_ijump:
case CMD_ilist:
case CMD_isearch:
@@ -1857,7 +1877,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)));
@@ -1910,7 +1930,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
// If we got a line, but no command, then go to the line.
// If we find a '|' or '\n' we set ea.nextcmd.
if (*ea.cmd == NUL || *ea.cmd == '"'
- || (ea.nextcmd = (char *)check_nextcmd((char_u *)ea.cmd)) != NULL) {
+ || (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL) {
// strange vi behaviour:
// ":3" jumps to line 3
// ":3|..." prints line 3
@@ -2419,8 +2439,12 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, bool
continue;
}
- // ":hide" and ":hide | cmd" are not modifiers
case 'h':
+ if (checkforcmd(&eap->cmd, "horizontal", 3)) {
+ cmod->cmod_split |= WSP_HOR;
+ continue;
+ }
+ // ":hide" and ":hide | cmd" are not modifiers
if (p != eap->cmd || !checkforcmd(&p, "hide", 3)
|| *p == NUL || ends_excmd(*p)) {
break;
@@ -2565,7 +2589,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 +2611,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;
}
@@ -2807,17 +2831,17 @@ static void append_command(char *cmd)
if (len > IOSIZE - 100) {
// Not enough space, truncate and put in "...".
d = (char *)IObuff + IOSIZE - 100;
- d -= utf_head_off(IObuff, (const char_u *)d);
+ d -= utf_head_off((char *)IObuff, d);
STRCPY(d, "...");
}
STRCAT(IObuff, ": ");
d = (char *)IObuff + STRLEN(IObuff);
- while (*s != NUL && (char_u *)d - IObuff + 5 < IOSIZE) {
+ while (*s != NUL && d - IObuff + 5 < IOSIZE) {
if ((char_u)s[0] == 0xc2 && (char_u)s[1] == 0xa0) {
s += 2;
STRCPY(d, "<a0>");
d += 4;
- } else if ((char_u *)d - IObuff + utfc_ptr2len(s) + 1 >= IOSIZE) {
+ } else if (d - IObuff + utfc_ptr2len(s) + 1 >= IOSIZE) {
break;
} else {
mb_copy_char((const char **)&s, &d);
@@ -3038,7 +3062,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;
@@ -3062,17 +3086,16 @@ void f_fullcommand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
- rettv->vval.v_string = (char *)vim_strsave(IS_USER_CMDIDX(ea.cmdidx)
- ? (char_u *)get_user_command_name(ea.useridx,
- ea.cmdidx)
- : (char_u *)cmdnames[ea.cmdidx].cmd_name);
+ rettv->vval.v_string = xstrdup(IS_USER_CMDIDX(ea.cmdidx)
+ ? get_user_command_name(ea.useridx, ea.cmdidx)
+ : cmdnames[ea.cmdidx].cmd_name);
}
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;
}
@@ -3121,7 +3144,7 @@ char *skip_range(const char *cmd, int *ctx)
}
}
if (*cmd != NUL) {
- cmd++;
+ cmd += utf_ptr2len(cmd);
}
}
@@ -3264,13 +3287,13 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
goto error;
}
if (skip) {
- cmd++;
+ cmd += utfc_ptr2len(cmd);
} else {
// Only accept a mark in another file when it is
// used by itself: ":'M".
MarkGet flag = to_other_file && cmd[1] == NUL ? kMarkAll : kMarkBufLocal;
- fmark_T *fm = mark_get(curbuf, curwin, NULL, flag, *cmd);
- cmd++;
+ fmark_T *fm = mark_get(curbuf, curwin, NULL, flag, utf_ptr2char(cmd));
+ cmd += utf_ptr2len(cmd);
if (fm != NULL && fm->fnum != curbuf->handle) {
// Jumped to another file.
lnum = curwin->w_cursor.lnum;
@@ -3294,7 +3317,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 +3593,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 +3657,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 ? p_gp : curbuf->b_p_gp)
+ : (*curbuf->b_p_mp == NUL ? (char *)p_mp : curbuf->b_p_mp);
arg = skipwhite(arg);
@@ -3646,7 +3672,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);
@@ -3668,7 +3694,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
// Decide to expand wildcards *before* replacing '%', '#', etc. If
// the file name contains a wildcard it should not cause expanding.
// (it will be expanded anyway if there is a wildcard before replacing).
- int has_wildcards = path_has_wildcard((char_u *)p);
+ int has_wildcards = path_has_wildcard(p);
while (*p != NUL) {
// Skip over `=expr`, wildcards in it are not expanded.
if (p[0] == '`' && p[1] == '=') {
@@ -3690,7 +3716,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,7 +3798,7 @@ 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);
+ expand_env_esc((char_u *)eap->arg, (char_u *)NameBuff, MAXPATHL, true, true, NULL);
has_wildcards = path_has_wildcard(NameBuff);
p = (char *)NameBuff;
} else {
@@ -3788,7 +3814,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);
@@ -3803,7 +3829,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
if (p_wic) {
options += WILD_ICASE;
}
- p = (char *)ExpandOne(&xpc, (char_u *)eap->arg, NULL, options, WILD_EXPAND_FREE);
+ p = ExpandOne(&xpc, eap->arg, NULL, options, WILD_EXPAND_FREE);
if (p == NULL) {
return FAIL;
}
@@ -3913,7 +3939,7 @@ void separate_nextcmd(exarg_T *eap)
STRMOVE(p - 1, p); // remove the '\'
p--;
} else {
- eap->nextcmd = (char *)check_nextcmd((char_u *)p);
+ eap->nextcmd = check_nextcmd(p);
*p = NUL;
break;
}
@@ -4042,7 +4068,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];
@@ -4088,9 +4114,9 @@ static int get_tabpage_arg(exarg_T *eap)
tab_number = (int)getdigits(&p, false, tab_number);
if (relative == 0) {
- if (STRCMP(p, "$") == 0) {
+ if (strcmp(p, "$") == 0) {
tab_number = LAST_TAB_NR;
- } else if (STRCMP(p, "#") == 0) {
+ } else if (strcmp(p, "#") == 0) {
if (valid_tabpage(lastused_tabpage)) {
tab_number = tabpage_index(lastused_tabpage);
} else {
@@ -4276,7 +4302,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,18 +4310,18 @@ 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.
///
/// @return NULL if it isn't, the following character if it is.
-char_u *check_nextcmd(char_u *p)
+char *check_nextcmd(char *p)
{
- char *s = skipwhite((char *)p);
+ char *s = skipwhite(p);
if (*s == '|' || *s == '\n') {
- return (char_u *)(s + 1);
+ return s + 1;
} else {
return NULL;
}
@@ -4322,7 +4348,7 @@ static int check_more(int message, bool forceit)
vim_snprintf((char *)buff, DIALOG_MSG_SIZE,
NGETTEXT("%d more file to edit. Quit anyway?",
"%d more files to edit. Quit anyway?", (unsigned long)n), n);
- if (vim_dialog_yesno(VIM_QUESTION, NULL, (char_u *)buff, 1) == VIM_YES) {
+ if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES) {
return OK;
}
return FAIL;
@@ -4812,7 +4838,6 @@ static void ex_print(exarg_T *eap)
if (++eap->line1 > eap->line2) {
break;
}
- ui_flush(); // show one line at a time
}
setpcmark();
// put cursor at last line
@@ -5013,8 +5038,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));
- ui_flush(); // output one line at a time
+ msg_outtrans_attr((char *)IObuff, HL_ATTR(HLF_T));
os_breakcheck();
FOR_ALL_WINDOWS_IN_TAB(wp, tp) {
@@ -5033,7 +5057,6 @@ static void ex_tabs(exarg_T *eap)
home_replace(wp->w_buffer, wp->w_buffer->b_fname, (char *)IObuff, IOSIZE, true);
}
msg_outtrans((char *)IObuff);
- ui_flush(); // output one line at a time
os_breakcheck();
}
}
@@ -5044,7 +5067,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 +5159,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);
@@ -5251,7 +5274,7 @@ static void ex_swapname(exarg_T *eap)
if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL) {
msg(_("No swap file"));
} else {
- msg((char *)curbuf->b_ml.ml_mfp->mf_fname);
+ msg(curbuf->b_ml.ml_mfp->mf_fname);
}
}
@@ -5298,7 +5321,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 +5389,7 @@ static void ex_read(exarg_T *eap)
deleted_lines_mark(lnum, 1L);
}
}
- redraw_curbuf_later(VALID);
+ redraw_curbuf_later(UPD_VALID);
}
}
}
@@ -5457,7 +5480,7 @@ bool changedir_func(char *new_dir, CdScope scope)
char *pdir = NULL;
// ":cd -": Change to previous directory
- if (STRCMP(new_dir, "-") == 0) {
+ if (strcmp(new_dir, "-") == 0) {
pdir = get_prevdir(scope);
if (pdir == NULL) {
emsg(_("E186: No previous directory"));
@@ -5466,8 +5489,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 +5503,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;
}
@@ -5521,27 +5544,26 @@ void ex_cd(exarg_T *eap)
// for non-UNIX ":cd" means: print current directory unless 'cdhome' is set
if (*new_dir == NUL && !p_cdh) {
ex_pwd(NULL);
- } else
+ return;
+ }
#endif
- {
- CdScope scope = kCdScopeGlobal;
- switch (eap->cmdidx) {
- case CMD_tcd:
- case CMD_tchdir:
- scope = kCdScopeTabpage;
- break;
- case CMD_lcd:
- case CMD_lchdir:
- scope = kCdScopeWindow;
- break;
- default:
- break;
- }
- if (changedir_func(new_dir, scope)) {
- // Echo the new current directory if the command was typed.
- if (KeyTyped || p_verbose >= 5) {
- ex_pwd(eap);
- }
+ CdScope scope = kCdScopeGlobal;
+ switch (eap->cmdidx) {
+ case CMD_tcd:
+ case CMD_tchdir:
+ scope = kCdScopeTabpage;
+ break;
+ case CMD_lcd:
+ case CMD_lchdir:
+ scope = kCdScopeWindow;
+ break;
+ default:
+ break;
+ }
+ if (changedir_func(new_dir, scope)) {
+ // Echo the new current directory if the command was typed.
+ if (KeyTyped || p_verbose >= 5) {
+ ex_pwd(eap);
}
}
}
@@ -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
@@ -5653,7 +5675,7 @@ static void ex_wincmd(exarg_T *eap)
p = eap->arg + 1;
}
- eap->nextcmd = (char *)check_nextcmd((char_u *)p);
+ eap->nextcmd = check_nextcmd(p);
p = skipwhite(p);
if (*p != NUL && *p != '"' && eap->nextcmd == NULL) {
emsg(_(e_invarg));
@@ -5985,7 +6007,7 @@ static void ex_redir(exarg_T *eap)
// Make register empty when not using @A-@Z and the
// command is valid.
if (*arg == NUL && !isupper(redir_reg)) {
- write_reg_contents(redir_reg, (char_u *)"", 0, false);
+ write_reg_contents(redir_reg, "", 0, false);
}
}
}
@@ -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,12 +6157,12 @@ 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;
}
#endif
- if (!forceit && *mode != 'a' && os_path_exists(fname)) {
+ if (!forceit && *mode != 'a' && os_path_exists((char *)fname)) {
semsg(_("E189: \"%s\" exists (add ! to override)"), 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);
@@ -6444,7 +6466,7 @@ static void ex_findpat(exarg_T *eap)
if (!ends_excmd(*p)) {
eap->errmsg = ex_errmsg(e_trailing_arg, p);
} else {
- eap->nextcmd = (char *)check_nextcmd((char_u *)p);
+ eap->nextcmd = check_nextcmd(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;
@@ -6541,7 +6563,7 @@ static void ex_tag_cmd(exarg_T *eap, char *name)
cmd = DT_LTAG;
}
- do_tag((char_u *)eap->arg, cmd, eap->addr_count > 0 ? (int)eap->line2 : 1,
+ do_tag(eap->arg, cmd, eap->addr_count > 0 ? (int)eap->line2 : 1,
eap->forceit, true);
}
@@ -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;
@@ -6686,7 +6712,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum
valid = 0; // Must have ":p:h" to be valid
} else {
result = curbuf->b_fname;
- tilde_file = STRCMP(result, "~") == 0;
+ tilde_file = strcmp(result, "~") == 0;
}
break;
@@ -6740,7 +6766,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum
valid = 0; // Must have ":p:h" to be valid
} else {
result = buf->b_fname;
- tilde_file = STRCMP(result, "~") == 0;
+ tilde_file = strcmp(result, "~") == 0;
}
}
break;
@@ -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]".
@@ -6944,16 +6986,16 @@ void dialog_msg(char *buff, char *format, char *fname)
/// ":behave {mswin,xterm}"
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);
- } 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);
+ if (strcmp(eap->arg, "mswin") == 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_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);
}
@@ -6999,7 +7041,7 @@ static void ex_filetype(exarg_T *eap)
}
break;
}
- if (STRCMP(arg, "on") == 0 || STRCMP(arg, "detect") == 0) {
+ if (strcmp(arg, "on") == 0 || strcmp(arg, "detect") == 0) {
if (*arg == 'o' || !filetype_detect) {
source_runtime(FILETYPE_FILE, DIP_ALL);
filetype_detect = kTrue;
@@ -7016,7 +7058,7 @@ static void ex_filetype(exarg_T *eap)
(void)do_doautocmd("filetypedetect BufRead", true, NULL);
do_modelines(0);
}
- } else if (STRCMP(arg, "off") == 0) {
+ } else if (strcmp(arg, "off") == 0) {
if (plugin || indent) {
if (plugin) {
source_runtime(FTPLUGOF_FILE, DIP_ALL);
@@ -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..f40149d07a 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)))
@@ -80,16 +79,14 @@ static void discard_pending_return(typval_T *p)
tv_free(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
- * 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;
+// 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
+// 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;
/// @return true when immediately aborting on error, or when an interrupt
/// occurred or an exception was thrown but not caught.
@@ -104,7 +101,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 +111,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 +124,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.
@@ -154,70 +151,58 @@ bool cause_errthrow(const char *mesg, bool severe, bool *ignore)
msglist_T *elem;
msglist_T **plist;
- /*
- * Do nothing when displaying the interrupt message or reporting an
- * uncaught exception (which has already been discarded then) at the top
- * level. Also when no exception can be thrown. The message will be
- * displayed by emsg().
- */
+ // Do nothing when displaying the interrupt message or reporting an
+ // uncaught exception (which has already been discarded then) at the top
+ // level. Also when no exception can be thrown. The message will be
+ // displayed by emsg().
if (suppress_errthrow) {
return false;
}
- /*
- * If emsg() has not been called previously, temporarily reset
- * "force_abort" until the throw point for error messages has been
- * reached. This ensures that aborting() returns the same value for all
- * errors that appear in the same command. This means particularly that
- * for parsing errors during expression evaluation emsg() will be called
- * multiply, even when the expression is evaluated from a finally clause
- * that was activated due to an aborting error, interrupt, or exception.
- */
+ // If emsg() has not been called previously, temporarily reset
+ // "force_abort" until the throw point for error messages has been
+ // reached. This ensures that aborting() returns the same value for all
+ // errors that appear in the same command. This means particularly that
+ // for parsing errors during expression evaluation emsg() will be called
+ // multiply, even when the expression is evaluated from a finally clause
+ // that was activated due to an aborting error, interrupt, or exception.
if (!did_emsg) {
cause_abort = force_abort;
- force_abort = FALSE;
- }
-
- /*
- * If no try conditional is active and no exception is being thrown and
- * there has not been an error in a try conditional or a throw so far, do
- * nothing (for compatibility of non-EH scripts). The message will then
- * be displayed by emsg(). When ":silent!" was used and we are not
- * 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) {
+ force_abort = false;
+ }
+
+ // If no try conditional is active and no exception is being thrown and
+ // there has not been an error in a try conditional or a throw so far, do
+ // nothing (for compatibility of non-EH scripts). The message will then
+ // be displayed by emsg(). When ":silent!" was used and we are not
+ // 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) && !did_throw) {
return false;
}
- /*
- * Ignore an interrupt message when inside a try conditional or when an
- * exception is being thrown or when an error in a try conditional or
- * throw has been detected previously. This is important in order that an
- * interrupt exception is catchable by the innermost try conditional and
- * not replaced by an interrupt message error exception.
- */
+ // Ignore an interrupt message when inside a try conditional or when an
+ // exception is being thrown or when an error in a try conditional or
+ // throw has been detected previously. This is important in order that an
+ // interrupt exception is catchable by the innermost try conditional and
+ // not replaced by an interrupt message error exception.
if (mesg == _(e_interr)) {
*ignore = true;
return true;
}
- /*
- * Ensure that all commands in nested function calls and sourced files
- * are aborted immediately.
- */
- cause_abort = TRUE;
-
- /*
- * When an exception is being thrown, some commands (like conditionals) are
- * not skipped. Errors in those commands may affect what of the subsequent
- * commands are regarded part of catch and finally clauses. Catching the
- * exception would then cause execution of commands not intended by the
- * user, who wouldn't even get aware of the problem. Therefore, discard the
- * exception currently being thrown to prevent it from being caught. Just
- * execute finally clauses and terminate.
- */
- if (current_exception) {
+ // Ensure that all commands in nested function calls and sourced files
+ // are aborted immediately.
+ cause_abort = true;
+
+ // When an exception is being thrown, some commands (like conditionals) are
+ // not skipped. Errors in those commands may affect what of the subsequent
+ // commands are regarded part of catch and finally clauses. Catching the
+ // exception would then cause execution of commands not intended by the
+ // user, who wouldn't even get aware of the problem. Therefore, discard the
+ // exception currently being thrown to prevent it from being caught. Just
+ // execute finally clauses and terminate.
+ 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.
@@ -229,25 +214,21 @@ bool cause_errthrow(const char *mesg, bool severe, bool *ignore)
#ifdef THROW_TEST
if (!THROW_ON_ERROR) {
- /*
- * Print error message immediately without searching for a matching
- * catch clause; just finally clauses are executed before the script
- * is terminated.
- */
+ // Print error message immediately without searching for a matching
+ // catch clause; just finally clauses are executed before the script
+ // is terminated.
return false;
} else // NOLINT(readability/braces)
#endif
{
- /*
- * Prepare the throw of an error exception, so that everything will
- * be aborted (except for executing finally clauses), until the error
- * exception is caught; if still uncaught at the top level, the error
- * message will be displayed and the script processing terminated
- * then. - This function has no access to the conditional stack.
- * Thus, the actual throw is made after the failing command has
- * returned. - Throw only the first of several errors in a row, except
- * a severe error is following.
- */
+ // Prepare the throw of an error exception, so that everything will
+ // be aborted (except for executing finally clauses), until the error
+ // exception is caught; if still uncaught at the top level, the error
+ // message will be displayed and the script processing terminated
+ // then. - This function has no access to the conditional stack.
+ // Thus, the actual throw is made after the failing command has
+ // returned. - Throw only the first of several errors in a row, except
+ // a severe error is following.
if (msg_list != NULL) {
plist = msg_list;
while (*plist != NULL) {
@@ -313,13 +294,11 @@ void free_global_msglist(void)
/// has returned (see do_one_cmd()).
void do_errthrow(cstack_T *cstack, char *cmdname)
{
- /*
- * Ensure that all commands in nested function calls and sourced files
- * are aborted immediately.
- */
+ // Ensure that all commands in nested function calls and sourced files
+ // 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 +313,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 +322,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 +337,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 +348,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;
}
@@ -456,11 +435,9 @@ static int throw_exception(void *value, except_type_T type, char *cmdname)
except_T *excp;
int should_free;
- /*
- * Disallow faking Interrupt or error exceptions as user exceptions. They
- * would be treated differently from real interrupt or error exceptions
- * when no active try block is found, see do_cmdline().
- */
+ // Disallow faking Interrupt or error exceptions as user exceptions. They
+ // would be treated differently from real interrupt or error exceptions
+ // when no active try block is found, see do_cmdline().
if (type == ET_USER) {
if (STRNCMP((char_u *)value, "Vim", 3) == 0
&& (((char_u *)value)[3] == NUL || ((char_u *)value)[3] == ':'
@@ -501,13 +478,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
@@ -552,15 +529,15 @@ static void discard_exception(except_T *excp, bool was_finished)
if (p_verbose >= 13 || debug_break_level > 0) {
int save_msg_silent = msg_silent;
- saved_IObuff = (char *)vim_strsave(IObuff);
+ saved_IObuff = xstrdup((char *)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 +573,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 +600,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
@@ -678,9 +656,7 @@ static void finish_exception(except_T *excp)
discard_exception(excp, true);
}
-/*
- * Flags specifying the message displayed by report_pending.
- */
+// Flags specifying the message displayed by report_pending.
#define RP_MAKE 0
#define RP_RESUME 1
#define RP_DISCARD 2
@@ -726,14 +702,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 +722,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 +806,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 +846,7 @@ void ex_endif(exarg_T *eap)
(void)do_intthrow(eap->cstack);
}
- --eap->cstack->cs_idx;
+ eap->cstack->cs_idx--;
}
}
@@ -958,14 +934,12 @@ void ex_while(exarg_T *eap)
if (cstack->cs_idx == CSTACK_LEN - 1) {
eap->errmsg = _("E585: :while/:for nesting too deep");
} else {
- /*
- * The loop flag is set when we have jumped back from the matching
- * ":endwhile" or ":endfor". When not set, need to initialise this
- * cstack entry.
- */
+ // The loop flag is set when we have jumped back from the matching
+ // ":endwhile" or ":endfor". When not set, need to initialise this
+ // 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] =
@@ -973,21 +947,17 @@ void ex_while(exarg_T *eap)
skip = CHECK_SKIP;
if (eap->cmdidx == CMD_while) {
- /*
- * ":while bool-expr"
- */
+ // ":while bool-expr"
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
} else {
void *fi;
- /*
- * ":for var in list-expr"
- */
+ // ":for var in list-expr"
if ((cstack->cs_lflags & CSL_HAD_LOOP) != 0) {
// 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 +968,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) {
@@ -1007,11 +977,9 @@ void ex_while(exarg_T *eap)
}
}
- /*
- * If this cstack entry was just initialised and is active, set the
- * loop flag, so do_cmdline() will set the line number in cs_line[].
- * If executing the command a second time, clear the loop flag.
- */
+ // If this cstack entry was just initialised and is active, set the
+ // loop flag, so do_cmdline() will set the line number in cs_line[].
+ // If executing the command a second time, clear the loop flag.
if (!skip && !error && result) {
cstack->cs_flags[cstack->cs_idx] |= (CSF_ACTIVE | CSF_TRUE);
cstack->cs_lflags ^= CSL_HAD_LOOP;
@@ -1046,10 +1014,8 @@ void ex_continue(exarg_T *eap)
if (cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR)) {
rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel);
- /*
- * Set CSL_HAD_CONT, so do_cmdline() will jump back to the
- * matching ":while".
- */
+ // Set CSL_HAD_CONT, so do_cmdline() will jump back to the
+ // matching ":while".
cstack->cs_lflags |= CSL_HAD_CONT; // let do_cmdline() handle it
} else {
// If a try conditional not in its finally clause is reached first,
@@ -1118,7 +1084,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 +1097,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)
@@ -1147,10 +1113,8 @@ void ex_endwhile(exarg_T *eap)
(void)do_intthrow(cstack);
}
- /*
- * Set loop flag, so do_cmdline() will jump back to the matching
- * ":while" or ":for".
- */
+ // Set loop flag, so do_cmdline() will jump back to the matching
+ // ":while" or ":for".
cstack->cs_lflags |= CSL_HAD_ENDLOOP;
}
}
@@ -1186,7 +1150,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,31 +1163,29 @@ 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);
if (idx >= 0) {
- /*
- * If this try conditional is active and we are before its first
- * ":catch", set THROWN so that the ":catch" commands will check
- * whether the exception matches. When the exception came from any of
- * the catch clauses, it will be made pending at the ":finally" (if
- * present) and rethrown at the ":endtry". This will also happen if
- * the try conditional is inactive. This is the case when we are
- * throwing an exception due to an error or interrupt on the way from
- * a preceding ":continue", ":break", ":return", ":finish", error or
- * interrupt (not converted to an exception) to the finally clause or
- * from a preceding throw of a user or error or interrupt exception to
- * the matching catch clause or the finally clause.
- */
+ // If this try conditional is active and we are before its first
+ // ":catch", set THROWN so that the ":catch" commands will check
+ // whether the exception matches. When the exception came from any of
+ // the catch clauses, it will be made pending at the ":finally" (if
+ // present) and rethrown at the ":endtry". This will also happen if
+ // the try conditional is inactive. This is the case when we are
+ // throwing an exception due to an error or interrupt on the way from
+ // a preceding ":continue", ":break", ":return", ":finish", error or
+ // interrupt (not converted to an exception) to the finally clause or
+ // from a preceding throw of a user or error or interrupt exception to
+ // the matching catch clause or the finally clause.
if (!(cstack->cs_flags[idx] & CSF_CAUGHT)) {
if (cstack->cs_flags[idx] & CSF_ACTIVE) {
cstack->cs_flags[idx] |= CSF_THROWN;
@@ -1237,6 +1199,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 +1212,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;
@@ -1261,22 +1225,20 @@ void ex_try(exarg_T *eap)
// that the finally clause needs to be executed.
cstack->cs_flags[cstack->cs_idx] |= CSF_ACTIVE | CSF_TRUE;
- /*
- * ":silent!", even when used in a try conditional, disables
- * displaying of error messages and conversion of errors to
- * exceptions. When the silent commands again open a try
- * conditional, save "emsg_silent" and reset it so that errors are
- * again converted to exceptions. The value is restored when that
- * try conditional is left. If it is left normally, the commands
- * following the ":endtry" are again silent. If it is left by
- * a ":continue", ":break", ":return", or ":finish", the commands
- * executed next are again silent. If it is left due to an
- * aborting error, an interrupt, or an exception, restoring
- * "emsg_silent" does not matter since we are already in the
- * aborting state and/or the exception has already been thrown.
- * The effect is then just freeing the memory that was allocated
- * to save the value.
- */
+ // ":silent!", even when used in a try conditional, disables
+ // displaying of error messages and conversion of errors to
+ // exceptions. When the silent commands again open a try
+ // conditional, save "emsg_silent" and reset it so that errors are
+ // again converted to exceptions. The value is restored when that
+ // try conditional is left. If it is left normally, the commands
+ // following the ":endtry" are again silent. If it is left by
+ // a ":continue", ":break", ":return", or ":finish", the commands
+ // executed next are again silent. If it is left due to an
+ // aborting error, an interrupt, or an exception, restoring
+ // "emsg_silent" does not matter since we are already in the
+ // aborting state and/or the exception has already been thrown.
+ // The effect is then just freeing the memory that was allocated
+ // to save the value.
if (emsg_silent) {
eslist_T *elem = xmalloc(sizeof(*elem));
elem->saved_emsg_silent = emsg_silent;
@@ -1314,7 +1276,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,27 +1295,23 @@ 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) {
- /*
- * Don't do something when no exception has been thrown or when the
- * 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)) {
+ // Don't do something when no exception has been thrown or when the
+ // corresponding try block never got active (because of an inactive
+ // surrounding conditional or after an error or interrupt or throw).
+ if (!did_throw || !(cstack->cs_flags[idx] & CSF_TRUE)) {
skip = true;
}
- /*
- * Check for a match only if an exception is thrown but not caught by
- * a previous ":catch". An exception that has replaced a discarded
- * exception is not checked (THROWN is not set then).
- */
+ // Check for a match only if an exception is thrown but not caught by
+ // a previous ":catch". An exception that has replaced a discarded
+ // exception is not checked (THROWN is not set then).
if (!skip && (cstack->cs_flags[idx] & CSF_THROWN)
&& !(cstack->cs_flags[idx] & CSF_CAUGHT)) {
if (end != NULL && *end != NUL && !ends_excmd(*skipwhite(end + 1))) {
@@ -1376,7 +1334,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 +1364,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,27 +1377,21 @@ 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,
- * finish the exception now. This happens also after errors except
- * when this ":catch" was after the ":finally" or not within
- * a ":try". Make the try conditional inactive so that the
- * following catch clauses are skipped. On an error or interrupt
- * after the preceding try block or catch clause was left by
- * a ":continue", ":break", ":return", or ":finish", discard the
- * pending action.
- */
- cleanup_conditionals(cstack, CSF_TRY, TRUE);
+ // If there is a preceding catch clause and it caught the exception,
+ // finish the exception now. This happens also after errors except
+ // when this ":catch" was after the ":finally" or not within
+ // a ":try". Make the try conditional inactive so that the
+ // following catch clauses are skipped. On an error or interrupt
+ // after the preceding try block or catch clause was left by
+ // a ":continue", ":break", ":return", or ":finish", discard the
+ // pending action.
+ cleanup_conditionals(cstack, CSF_TRY, true);
}
}
if (end != NULL) {
- eap->nextcmd = (char *)find_nextcmd((char_u *)end);
+ eap->nextcmd = find_nextcmd(end);
}
}
@@ -1447,7 +1399,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 +1408,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 +1429,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) {
@@ -1499,32 +1449,28 @@ void ex_finally(exarg_T *eap)
(void)do_intthrow(cstack);
}
- /*
- * If there is a preceding catch clause and it caught the exception,
- * finish the exception now. This happens also after errors except
- * when this is a multiple ":finally" or one not within a ":try".
- * After an error or interrupt, this also discards a pending
- * ":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) {
+ // If there is a preceding catch clause and it caught the exception,
+ // finish the exception now. This happens also after errors except
+ // when this is a multiple ":finally" or one not within a ":try".
+ // After an error or interrupt, this also discards a pending
+ // ":continue", ":break", ":finish", or ":return" from the preceding
+ // try block or catch clause.
+ 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 +1479,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 +1493,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 +1530,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 +1544,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();
}
@@ -1618,13 +1558,11 @@ void ex_endtry(exarg_T *eap)
} else {
idx = cstack->cs_idx;
- /*
- * If we stopped with the exception currently being thrown at this
- * try conditional since we didn't know that it doesn't have
- * a finally clause, we need to rethrow it after closing the try
- * conditional.
- */
- if (current_exception
+ // If we stopped with the exception currently being thrown at this
+ // try conditional since we didn't know that it doesn't have
+ // a finally clause, we need to rethrow it after closing the try
+ // conditional.
+ if (did_throw
&& (cstack->cs_flags[idx] & CSF_TRUE)
&& !(cstack->cs_flags[idx] & CSF_FINALLY)) {
rethrow = true;
@@ -1648,21 +1586,19 @@ 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;
}
}
}
- /*
- * If a ":return" is pending, we need to resume it after closing the
- * try conditional; remember the return value. If there was a finally
- * clause making an exception pending, we need to rethrow it. Make it
- * the exception currently being thrown.
- */
+ // If a ":return" is pending, we need to resume it after closing the
+ // try conditional; remember the return value. If there was a finally
+ // clause making an exception pending, we need to rethrow it. Make it
+ // the exception currently being thrown.
if (!skip) {
pending = cstack->cs_pending[idx];
cstack->cs_pending[idx] = CSTP_NONE;
@@ -1673,17 +1609,15 @@ void ex_endtry(exarg_T *eap)
}
}
- /*
- * Discard anything pending on an error, interrupt, or throw in the
- * finally clause. If there was no ":finally", discard a pending
- * ":continue", ":break", ":return", or ":finish" if an error or
- * interrupt occurred afterwards, but before the ":endtry" was reached.
- * If an exception was caught by the last of the catch clauses and there
- * was no finally clause, finish the exception now. This happens also
- * 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);
+ // Discard anything pending on an error, interrupt, or throw in the
+ // finally clause. If there was no ":finally", discard a pending
+ // ":continue", ":break", ":return", or ":finish" if an error or
+ // interrupt occurred afterwards, but before the ":endtry" was reached.
+ // If an exception was caught by the last of the catch clauses and there
+ // was no finally clause, finish the exception now. This happens also
+ // 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);
if (cstack->cs_idx >= 0 && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) {
cstack->cs_idx--;
@@ -1712,16 +1646,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:
@@ -1745,18 +1679,16 @@ void ex_endtry(exarg_T *eap)
}
}
-/*
- * enter_cleanup() and leave_cleanup()
- *
- * Functions to be called before/after invoking a sequence of autocommands for
- * cleanup for a failed command. (Failure means here that a call to emsg()
- * has been made, an interrupt occurred, or there is an uncaught exception
- * from a previous autocommand execution of the same command.)
- *
- * Call enter_cleanup() with a pointer to a cleanup_T and pass the same
- * pointer to leave_cleanup(). The cleanup_T structure stores the pending
- * error/interrupt/exception state.
- */
+// enter_cleanup() and leave_cleanup()
+//
+// Functions to be called before/after invoking a sequence of autocommands for
+// cleanup for a failed command. (Failure means here that a call to emsg()
+// has been made, an interrupt occurred, or there is an uncaught exception
+// from a previous autocommand execution of the same command.)
+//
+// Call enter_cleanup() with a pointer to a cleanup_T and pass the same
+// pointer to leave_cleanup(). The cleanup_T structure stores the pending
+// error/interrupt/exception state.
/// This function works a bit like ex_finally() except that there was not
/// actually an extra try block around the part that failed and an error or
@@ -1768,35 +1700,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);
@@ -1844,18 +1773,14 @@ void leave_cleanup(cleanup_T *csp)
if (msg_list != NULL) {
free_global_msglist();
}
- }
- /*
- * If there was no new error, interrupt, or throw between the calls
- * to enter_cleanup() and leave_cleanup(), restore the pending
- * error/interrupt/exception state.
- */
- else {
- /*
- * If there was an exception being thrown when enter_cleanup() was
- * called, we need to rethrow it. Make it the exception currently
- * being thrown.
- */
+ } else {
+ // If there was no new error, interrupt, or throw between the calls
+ // to enter_cleanup() and leave_cleanup(), restore the pending
+ // error/interrupt/exception state.
+
+ // If there was an exception being thrown when enter_cleanup() was
+ // called, we need to rethrow it. Make it the exception currently
+ // being thrown.
if (pending & CSTP_THROW) {
current_exception = csp->exception;
} else if (pending & CSTP_ERROR) {
@@ -1863,10 +1788,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 +1799,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 +1820,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,16 +1829,14 @@ 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
- * search. There may also be a pending ":continue", ":break",
- * ":return", or ":finish" before the finally clause. We must not
- * discard it, unless an error or interrupt occurred afterwards.
- */
+ // Discard anything pending in a finally clause and continue the
+ // search. There may also be a pending ":continue", ":break",
+ // ":return", or ":finish" before the finally clause. We must not
+ // discard it, unless an error or interrupt occurred afterwards.
if (did_emsg || got_int || (cstack->cs_flags[idx] & CSF_FINALLY)) {
switch (cstack->cs_pending[idx]) {
case CSTP_NONE:
@@ -1949,11 +1872,9 @@ int cleanup_conditionals(cstack_T *cstack, int searched_cond, int inclusive)
}
}
- /*
- * Stop at a try conditional not in its finally clause. If this try
- * conditional is in an active catch clause, finish the caught
- * exception.
- */
+ // Stop at a try conditional not in its finally clause. If this try
+ // conditional is in an active catch clause, finish the caught
+ // exception.
if (!(cstack->cs_flags[idx] & CSF_FINALLY)) {
if ((cstack->cs_flags[idx] & CSF_ACTIVE)
&& (cstack->cs_flags[idx] & CSF_CAUGHT) && !(cstack->cs_flags[idx] & CSF_FINISHED)) {
@@ -1968,31 +1889,29 @@ 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)) {
break;
}
- /*
- * When leaving a try conditional that reset "emsg_silent" on its
- * entry after saving the original value, restore that value here and
- * free the memory used to store it.
- */
+ // When leaving a try conditional that reset "emsg_silent" on its
+ // entry after saving the original value, restore that value here and
+ // free the memory used to store it.
if ((cstack->cs_flags[idx] & CSF_TRY)
&& (cstack->cs_flags[idx] & CSF_SILENT)) {
eslist_T *elem;
@@ -2036,7 +1955,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 +1965,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 +1983,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..7d48158b4f 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1,9 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * ex_getln.c: Functions for entering and editing an Ex command line.
- */
+// ex_getln.c: Functions for entering and editing an Ex command line.
#include <assert.h>
#include <inttypes.h>
@@ -105,9 +103,9 @@ 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.
- char_u *lookfor; // string to match
+ int gotesc; // true when <ESC> just typed
+ int do_abbr; // when true check for abbr.
+ char *lookfor; // string to match
int hiscnt; // current history line in use
int save_hiscnt; // history line before attempting
// to jump to next match
@@ -118,7 +116,7 @@ typedef struct command_line_state {
int res;
int save_msg_scroll;
int save_State; // remember State when called
- char_u *save_p_icm;
+ char *save_p_icm;
int some_key_typed; // one of the keys was typed
// mouse drag and release events are ignored, unless they are
// preceded with a mouse down event
@@ -170,6 +168,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
@@ -253,7 +253,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
exarg_T ea = {
.line1 = 1,
.line2 = 1,
- .cmd = (char *)ccline.cmdbuff,
+ .cmd = ccline.cmdbuff,
.addr_type = ADDR_LINES,
};
@@ -313,7 +313,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) {
@@ -326,7 +326,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
int empty;
*end = NUL;
- empty = empty_pattern((char_u *)p);
+ empty = empty_pattern(p);
*end = c;
if (empty) {
goto theend;
@@ -334,7 +334,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
}
// found a non-empty pattern or //
- *skiplen = (int)((char_u *)p - ccline.cmdbuff);
+ *skiplen = (int)(p - ccline.cmdbuff);
*patlen = (int)(end - p);
// parse the address range
@@ -407,7 +407,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
int found; // do_search() result
// Use the previous pattern for ":s//".
- next_char = ccline.cmdbuff[skiplen + patlen];
+ next_char = (char_u)ccline.cmdbuff[skiplen + patlen];
use_last_pat = patlen == 0 && skiplen > 0
&& ccline.cmdbuff[skiplen - 1] == next_char;
@@ -415,7 +415,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();
@@ -434,9 +434,9 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
.sa_tm = &tm,
};
found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim,
- ccline.cmdbuff + skiplen, count,
+ (char_u *)ccline.cmdbuff + skiplen, count,
search_flags, &sia);
- ccline.cmdbuff[skiplen + patlen] = next_char;
+ ccline.cmdbuff[skiplen + patlen] = (char)next_char;
emsg_off--;
if (curwin->w_cursor.lnum < search_first_line
|| curwin->w_cursor.lnum > search_last_line) {
@@ -485,13 +485,13 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
// Disable 'hlsearch' highlighting if the pattern matches
// everything. Avoids a flash when typing "foo\|".
if (!use_last_pat) {
- next_char = ccline.cmdbuff[skiplen + patlen];
+ next_char = (char_u)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;
+ ccline.cmdbuff[skiplen + patlen] = (char)next_char;
}
validate_cursor();
@@ -500,7 +500,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();
@@ -546,7 +546,7 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s)
// command line has no uppercase characters, convert
// the character to lowercase
if (p_ic && p_scs
- && !pat_has_uppercase(ccline.cmdbuff + skiplen)) {
+ && !pat_has_uppercase((char_u *)ccline.cmdbuff + skiplen)) {
*c = mb_tolower(*c);
}
if (*c == search_delim
@@ -585,9 +585,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 +611,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 +632,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 = xstrdup(p_icm);
init_incsearch_state(&s->is_state);
CmdlineInfo save_ccline;
bool did_save_ccline = false;
@@ -722,7 +722,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
if (ccline.input_fn) {
s->xpc.xp_context = ccline.xp_context;
- s->xpc.xp_pattern = (char *)ccline.cmdbuff;
+ s->xpc.xp_pattern = ccline.cmdbuff;
s->xpc.xp_arg = (char *)ccline.xp_arg;
}
@@ -852,7 +852,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 = xstrdup(ccline.cmdbuff);
}
}
@@ -879,11 +879,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init
need_wait_return = false;
}
- set_string_option_direct("icm", -1, (char *)s->save_p_icm, OPT_FREE, SID_NONE);
+ set_string_option_direct("icm", -1, s->save_p_icm, OPT_FREE, SID_NONE);
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();
@@ -895,7 +895,7 @@ theend:
xfree(ccline.last_colors.cmdbuff);
kv_destroy(ccline.last_colors.colors);
- char_u *p = ccline.cmdbuff;
+ char_u *p = (char_u *)ccline.cmdbuff;
if (ui_has(kUICmdline)) {
ui_call_cmdline_hide(ccline.level);
@@ -916,7 +916,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;
}
@@ -1087,7 +1087,7 @@ static int command_line_execute(VimState *state, int key)
s->c = get_expr_register();
if (s->c == '=') {
textlock++;
- p = get_expr_line();
+ p = (char_u *)get_expr_line();
textlock--;
if (p != NULL) {
@@ -1260,7 +1260,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 +1277,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);
@@ -1334,7 +1337,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
skiplen = 0;
patlen = (int)STRLEN(pat);
} else {
- pat = ccline.cmdbuff + skiplen;
+ pat = (char_u *)ccline.cmdbuff + skiplen;
}
if (next_match) {
@@ -1395,7 +1398,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,28 +1477,28 @@ 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) {
- ccline.cmdpos += mb_off_next(ccline.cmdbuff,
- ccline.cmdbuff + ccline.cmdpos);
+ ccline.cmdpos += mb_off_next((char_u *)ccline.cmdbuff,
+ (char_u *)ccline.cmdbuff + ccline.cmdpos);
}
if (ccline.cmdpos > 0) {
char_u *p;
int j = ccline.cmdpos;
- p = mb_prevptr(ccline.cmdbuff, ccline.cmdbuff + j);
+ p = mb_prevptr((char_u *)ccline.cmdbuff, (char_u *)ccline.cmdbuff + j);
if (s->c == Ctrl_W) {
- while (p > ccline.cmdbuff && ascii_isspace(*p)) {
- p = mb_prevptr(ccline.cmdbuff, p);
+ while (p > (char_u *)ccline.cmdbuff && ascii_isspace(*p)) {
+ p = mb_prevptr((char_u *)ccline.cmdbuff, p);
}
int i = mb_get_class(p);
- while (p > ccline.cmdbuff && mb_get_class(p) == i) {
- p = mb_prevptr(ccline.cmdbuff, p);
+ while (p > (char_u *)ccline.cmdbuff && mb_get_class(p) == i) {
+ p = mb_prevptr((char_u *)ccline.cmdbuff, p);
}
if (mb_get_class(p) != i) {
@@ -1503,7 +1506,7 @@ static int command_line_handle_key(CommandLineState *s)
}
}
- ccline.cmdpos = (int)(p - ccline.cmdbuff);
+ ccline.cmdpos = (int)(p - (char_u *)ccline.cmdbuff);
ccline.cmdlen -= j - ccline.cmdpos;
int i = ccline.cmdpos;
@@ -1683,7 +1686,7 @@ static int command_line_handle_key(CommandLineState *s)
}
ccline.cmdspos += cells;
- ccline.cmdpos += utfc_ptr2len((char *)ccline.cmdbuff + ccline.cmdpos);
+ ccline.cmdpos += utfc_ptr2len(ccline.cmdbuff + ccline.cmdpos);
} while ((s->c == K_S_RIGHT || s->c == K_C_RIGHT
|| (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)))
&& ccline.cmdbuff[ccline.cmdpos] != ' ');
@@ -1756,7 +1759,7 @@ static int command_line_handle_key(CommandLineState *s)
// Count ">" for double-wide char that doesn't fit.
correct_screencol(ccline.cmdpos, cells, &ccline.cmdspos);
- ccline.cmdpos += utfc_ptr2len((char *)ccline.cmdbuff + ccline.cmdpos) - 1;
+ ccline.cmdpos += utfc_ptr2len(ccline.cmdbuff + ccline.cmdpos) - 1;
ccline.cmdspos += cells;
}
return command_line_not_changed(s);
@@ -1798,13 +1801,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:
@@ -1846,7 +1853,7 @@ static int command_line_handle_key(CommandLineState *s)
// save current command string so it can be restored later
if (s->lookfor == NULL) {
- s->lookfor = vim_strsave(ccline.cmdbuff);
+ s->lookfor = xstrdup(ccline.cmdbuff);
s->lookfor[ccline.cmdpos] = NUL;
}
@@ -1863,13 +1870,13 @@ static int command_line_handle_key(CommandLineState *s)
XFREE_CLEAR(ccline.cmdbuff);
s->xpc.xp_context = EXPAND_NOTHING;
if (s->hiscnt == get_hislen()) {
- p = s->lookfor; // back to the old one
+ p = (char_u *)s->lookfor; // back to the old one
} else {
- p = get_histentry(s->histype)[s->hiscnt].hisstr;
+ p = (char_u *)get_histentry(s->histype)[s->hiscnt].hisstr;
}
if (s->histype == HIST_SEARCH
- && p != s->lookfor
+ && p != (char_u *)s->lookfor
&& (old_firstc = p[STRLEN(p) + 1]) != s->firstc) {
// Correct for the separator character used when
// adding the history entry vs the one used now.
@@ -1883,7 +1890,7 @@ static int command_line_handle_key(CommandLineState *s)
if (p[j] == old_firstc
&& (j == 0 || p[j - 1] != '\\')) {
if (i > 0) {
- ccline.cmdbuff[len] = (char_u)s->firstc;
+ ccline.cmdbuff[len] = (char)s->firstc;
}
} else {
// Escape new sep, unless it is already
@@ -1897,7 +1904,7 @@ static int command_line_handle_key(CommandLineState *s)
}
if (i > 0) {
- ccline.cmdbuff[len] = p[j];
+ ccline.cmdbuff[len] = (char)p[j];
}
}
len++;
@@ -1998,7 +2005,7 @@ static int command_line_handle_key(CommandLineState *s)
} else {
int j = utf_char2bytes(s->c, (char *)IObuff);
IObuff[j] = NUL; // exclude composing chars
- put_on_cmdline(IObuff, j, true);
+ put_on_cmdline((char_u *)IObuff, j, true);
}
return command_line_changed(s);
}
@@ -2018,7 +2025,7 @@ static int command_line_not_changed(CommandLineState *s)
/// Guess that the pattern matches everything. Only finds specific cases, such
/// as a trailing \|, which can happen while typing a pattern.
-static int empty_pattern(char_u *p)
+static int empty_pattern(char *p)
{
size_t n = STRLEN(p);
@@ -2272,7 +2279,7 @@ static bool cmdpreview_may_show(CommandLineState *s)
CmdParseInfo cmdinfo;
// Copy the command line so we can modify it.
int cmdpreview_type = 0;
- char *cmdline = xstrdup((char *)ccline.cmdbuff);
+ char *cmdline = xstrdup(ccline.cmdbuff);
char *errormsg = NULL;
emsg_off++; // Block errors when parsing the command line, and don't update v:errmsg
if (!parse_cmdline(cmdline, &ea, &cmdinfo, &errormsg)) {
@@ -2343,7 +2350,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 +2371,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 +2381,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 +2401,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 +2418,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 +2539,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)
@@ -2536,10 +2601,8 @@ bool text_locked(void)
return textlock != 0;
}
-/*
- * Give an error message for a command that isn't allowed while the cmdline
- * window is open or editing the cmdline in another way.
- */
+// Give an error message for a command that isn't allowed while the cmdline
+// window is open or editing the cmdline in another way.
void text_locked_msg(void)
{
emsg(_(get_text_locked_msg()));
@@ -2592,7 +2655,7 @@ static int cmdline_charsize(int idx)
if (cmdline_star > 0) { // showing '*', always 1 position
return 1;
}
- return ptr2cells((char *)ccline.cmdbuff + idx);
+ return ptr2cells(ccline.cmdbuff + idx);
}
/// Compute the offset of the cursor on the command line for the prompt and
@@ -2618,7 +2681,7 @@ int cmd_screencol(int bytepos)
}
for (int i = 0; i < ccline.cmdlen && i < bytepos;
- i += utfc_ptr2len((char *)ccline.cmdbuff + i)) {
+ i += utfc_ptr2len(ccline.cmdbuff + i)) {
int c = cmdline_charsize(i);
// Count ">" for double-wide multi-byte char that doesn't fit.
correct_screencol(i, c, &col);
@@ -2637,8 +2700,8 @@ int cmd_screencol(int bytepos)
/// character that doesn't fit, so that a ">" must be displayed.
static void correct_screencol(int idx, int cells, int *col)
{
- if (utfc_ptr2len((char *)ccline.cmdbuff + idx) > 1
- && utf_ptr2cells((char *)ccline.cmdbuff + idx) > 1
+ if (utfc_ptr2len(ccline.cmdbuff + idx) > 1
+ && utf_ptr2cells(ccline.cmdbuff + idx) > 1
&& (*col) % Columns + cells > Columns) {
(*col)++;
}
@@ -2671,15 +2734,11 @@ bool cmdline_at_end(void)
return (ccline.cmdpos >= ccline.cmdlen);
}
-/*
- * Allocate a new command line buffer.
- * Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
- */
+// Allocate a new command line buffer.
+// Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
static void alloc_cmdbuff(int len)
{
- /*
- * give some extra space to avoid having to allocate all the time
- */
+ // give some extra space to avoid having to allocate all the time
if (len < 80) {
len = 100;
} else {
@@ -2697,7 +2756,7 @@ void realloc_cmdbuff(int len)
return; // no need to resize
}
- char_u *p = ccline.cmdbuff;
+ char_u *p = (char_u *)ccline.cmdbuff;
alloc_cmdbuff(len); // will get some more
// There isn't always a NUL after the command, but it may need to be
// there, thus copy up to the NUL and add a NUL.
@@ -2714,7 +2773,7 @@ void realloc_cmdbuff(int len)
// If xp_pattern points inside the old cmdbuff it needs to be adjusted
// to point into the newly allocated memory.
if (i >= 0 && i <= ccline.cmdlen) {
- ccline.xpc->xp_pattern = (char *)ccline.cmdbuff + i;
+ ccline.xpc->xp_pattern = ccline.cmdbuff + i;
}
}
}
@@ -2822,7 +2881,7 @@ static bool color_cmdline(CmdlineInfo *colored_ccline)
// Check whether result of the previous call is still valid.
if (ccline_colors->prompt_id == colored_ccline->prompt_id
&& ccline_colors->cmdbuff != NULL
- && STRCMP(ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) {
+ && strcmp(ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) {
return ret;
}
@@ -2837,7 +2896,7 @@ static bool color_cmdline(CmdlineInfo *colored_ccline)
bool arg_allocated = false;
typval_T arg = {
.v_type = VAR_STRING,
- .vval.v_string = (char *)colored_ccline->cmdbuff,
+ .vval.v_string = colored_ccline->cmdbuff,
};
typval_T tv = { .v_type = VAR_UNKNOWN };
@@ -3021,10 +3080,8 @@ color_cmdline_error:
#undef PRINT_ERRMSG
}
-/*
- * Draw part of the cmdline at the current cursor position. But draw stars
- * when cmdline_star is TRUE.
- */
+// Draw part of the cmdline at the current cursor position. But draw stars
+// when cmdline_star is true.
static void draw_cmdline(int start, int len)
{
if (!color_cmdline(&ccline)) {
@@ -3040,16 +3097,16 @@ static void draw_cmdline(int start, int len)
if (cmdline_star > 0) {
for (int i = 0; i < len; i++) {
msg_putchar('*');
- i += utfc_ptr2len((char *)ccline.cmdbuff + start + i) - 1;
+ i += utfc_ptr2len(ccline.cmdbuff + start + i) - 1;
}
} else if (p_arshape && !p_tbidi && len > 0) {
bool do_arabicshape = false;
int mb_l;
for (int i = start; i < start + len; i += mb_l) {
- char_u *p = ccline.cmdbuff + i;
+ char_u *p = (char_u *)ccline.cmdbuff + i;
int u8cc[MAX_MCO];
int u8c = utfc_ptr2char_len(p, u8cc, start + len - i);
- mb_l = utfc_ptr2len_len(p, start + len - i);
+ mb_l = utfc_ptr2len_len((char *)p, start + len - i);
if (ARABIC_CHAR(u8c)) {
do_arabicshape = true;
break;
@@ -3073,7 +3130,7 @@ static void draw_cmdline(int start, int len)
}
int newlen = 0;
- if (utf_iscomposing(utf_ptr2char((char *)ccline.cmdbuff + start))) {
+ if (utf_iscomposing(utf_ptr2char(ccline.cmdbuff + start))) {
// Prepend a space to draw the leading composing char on.
arshape_buf[0] = ' ';
newlen = 1;
@@ -3082,10 +3139,10 @@ static void draw_cmdline(int start, int len)
int prev_c = 0;
int prev_c1 = 0;
for (int i = start; i < start + len; i += mb_l) {
- char_u *p = ccline.cmdbuff + i;
+ char_u *p = (char_u *)ccline.cmdbuff + i;
int u8cc[MAX_MCO];
int u8c = utfc_ptr2char_len(p, u8cc, start + len - i);
- mb_l = utfc_ptr2len_len(p, start + len - i);
+ mb_l = utfc_ptr2len_len((char *)p, start + len - i);
if (ARABIC_CHAR(u8c)) {
int pc;
int pc1 = 0;
@@ -3131,7 +3188,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)) {
@@ -3154,12 +3211,11 @@ 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);
size_t len = 0;
- for (char_u *p = ccline.cmdbuff; *p; MB_PTR_ADV(p)) {
+ for (char_u *p = (char_u *)ccline.cmdbuff; *p; MB_PTR_ADV(p)) {
len++;
}
char *buf = arena_alloc(&arena, len, false);
@@ -3199,7 +3255,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)
@@ -3276,11 +3332,9 @@ 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.
- * "c" must be printable (fit in one display cell)!
- */
+// 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.
+// "c" must be printable (fit in one display cell)!
void putcmdline(char c, int shift)
{
if (cmd_silent) {
@@ -3304,7 +3358,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) {
@@ -3314,7 +3368,7 @@ void unputcmdline(void)
if (ccline.cmdlen == ccline.cmdpos && !ui_has(kUICmdline)) {
msg_putchar(' ');
} else {
- draw_cmdline(ccline.cmdpos, utfc_ptr2len((char *)ccline.cmdbuff + ccline.cmdpos));
+ draw_cmdline(ccline.cmdpos, utfc_ptr2len(ccline.cmdbuff + ccline.cmdpos));
}
msg_no_more = false;
cursorcmd();
@@ -3322,14 +3376,12 @@ void unputcmdline(void)
ui_cursor_shape();
}
-/*
- * 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
- * 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
- * called afterwards.
- */
+// 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
+// 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
+// called afterwards.
void put_on_cmdline(char_u *str, int len, int redraw)
{
int i;
@@ -3356,7 +3408,7 @@ void put_on_cmdline(char_u *str, int len, int redraw)
// Count nr of bytes in cmdline that are overwritten by these
// characters.
for (i = ccline.cmdpos; i < ccline.cmdlen && m > 0;
- i += utfc_ptr2len((char *)ccline.cmdbuff + i)) {
+ i += utfc_ptr2len(ccline.cmdbuff + i)) {
m--;
}
if (i < ccline.cmdlen) {
@@ -3374,17 +3426,17 @@ void put_on_cmdline(char_u *str, int len, int redraw)
// When the inserted text starts with a composing character,
// backup to the character before it. There could be two of them.
i = 0;
- c = utf_ptr2char((char *)ccline.cmdbuff + ccline.cmdpos);
+ c = utf_ptr2char(ccline.cmdbuff + ccline.cmdpos);
while (ccline.cmdpos > 0 && utf_iscomposing(c)) {
i = utf_head_off(ccline.cmdbuff, ccline.cmdbuff + ccline.cmdpos - 1) + 1;
ccline.cmdpos -= i;
len += i;
- c = utf_ptr2char((char *)ccline.cmdbuff + ccline.cmdpos);
+ c = utf_ptr2char(ccline.cmdbuff + ccline.cmdpos);
}
if (i == 0 && ccline.cmdpos > 0 && arabic_maycombine(c)) {
// Check the previous character for Arabic combining pair.
i = utf_head_off(ccline.cmdbuff, ccline.cmdbuff + ccline.cmdpos - 1) + 1;
- if (arabic_combine(utf_ptr2char((char *)ccline.cmdbuff + ccline.cmdpos - i), c)) {
+ if (arabic_combine(utf_ptr2char(ccline.cmdbuff + ccline.cmdpos - i), c)) {
ccline.cmdpos -= i;
len += i;
} else {
@@ -3393,7 +3445,7 @@ void put_on_cmdline(char_u *str, int len, int redraw)
}
if (i != 0) {
// Also backup the cursor position.
- i = ptr2cells((char *)ccline.cmdbuff + ccline.cmdpos);
+ i = ptr2cells(ccline.cmdbuff + ccline.cmdpos);
ccline.cmdspos -= i;
msg_col -= i;
if (msg_col < 0) {
@@ -3404,7 +3456,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 +3464,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;
@@ -3432,7 +3484,7 @@ void put_on_cmdline(char_u *str, int len, int redraw)
if (ccline.cmdspos + c < m) {
ccline.cmdspos += c;
}
- c = utfc_ptr2len((char *)ccline.cmdbuff + ccline.cmdpos) - 1;
+ c = utfc_ptr2len(ccline.cmdbuff + ccline.cmdpos) - 1;
if (c > len - i - 1) {
c = len - i - 1;
}
@@ -3514,14 +3566,14 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
int len;
// Locate start of last word in the cmd buffer.
- for (w = ccline.cmdbuff + ccline.cmdpos; w > ccline.cmdbuff;) {
- len = utf_head_off(ccline.cmdbuff, w - 1) + 1;
+ for (w = (char_u *)ccline.cmdbuff + ccline.cmdpos; w > (char_u *)ccline.cmdbuff;) {
+ len = utf_head_off(ccline.cmdbuff, (char *)w - 1) + 1;
if (!vim_iswordc(utf_ptr2char((char *)w - len))) {
break;
}
w -= len;
}
- len = (int)((ccline.cmdbuff + ccline.cmdpos) - w);
+ len = (int)(((char_u *)ccline.cmdbuff + ccline.cmdpos) - w);
if (p_ic ? STRNICMP(w, arg, len) == 0 : STRNCMP(w, arg, len) == 0) {
p += len;
}
@@ -3537,18 +3589,16 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
return cmdline_paste_reg(regname, literally, 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
- * line.
- */
+// 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
+// line.
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;
@@ -3609,9 +3659,7 @@ static void redrawcmdprompt(void)
}
}
-/*
- * Redraw what is currently on the command line.
- */
+// Redraw what is currently on the command line.
void redrawcmd(void)
{
if (cmd_silent) {
@@ -3637,7 +3685,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;
@@ -3648,11 +3696,9 @@ void redrawcmd(void)
putcmdline(ccline.special_char, ccline.special_shift);
}
- /*
- * 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
+ // 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
// Typing ':' at the more prompt may set skip_redraw. We don't want this
// in cmdline mode.
@@ -3728,12 +3774,10 @@ void gotocmdline(bool clr)
cmd_cursor_goto(cmdline_row, 0);
}
-/*
- * Check the word in front of the cursor for an abbreviation.
- * Called when the non-id character "c" has been entered.
- * When an abbreviation is recognized it is removed from the text with
- * backspaces and the replacement string is inserted, followed by "c".
- */
+// Check the word in front of the cursor for an abbreviation.
+// Called when the non-id character "c" has been entered.
+// When an abbreviation is recognized it is removed from the text with
+// backspaces and the replacement string is inserted, followed by "c".
static int ccheck_abbr(int c)
{
int spos = 0;
@@ -3757,7 +3801,7 @@ static int ccheck_abbr(int c)
spos = 0;
}
- return check_abbr(c, ccline.cmdbuff, ccline.cmdpos, spos);
+ return check_abbr(c, (char_u *)ccline.cmdbuff, ccline.cmdpos, spos);
}
/// Escape special characters in "fname", depending on "what":
@@ -3867,8 +3911,42 @@ 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.
+///
+/// @return NULL when something is wrong.
+static char *get_cmdline_str(void)
+{
+ if (cmdline_star > 0) {
+ return NULL;
+ }
+ CmdlineInfo *p = get_ccline_ptr();
+
+ if (p == NULL) {
+ return NULL;
+ }
+ return xstrnsave(p->cmdbuff, (size_t)p->cmdlen);
+}
+
/// Get the current command-line completion type.
-char_u *get_cmdline_completion(void)
+static char *get_cmdline_completion(void)
{
if (cmdline_star > 0) {
return NULL;
@@ -3879,64 +3957,79 @@ char_u *get_cmdline_completion(void)
set_expand_context(p->xpc);
char *cmd_compl = get_user_cmd_complete(p->xpc, p->xpc->xp_context);
if (cmd_compl != NULL) {
- return vim_strsave((char_u *)cmd_compl);
+ return xstrdup(cmd_compl);
}
}
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 = 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 = 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;
+}
+
+/// "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();
}
-/// Get the command line cursor screen position.
-int get_cmdline_screen_pos(void)
+/// 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 +4047,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 (tv_check_for_string_arg(argvars, 0) == FAIL
+ || tv_check_for_opt_number_arg(argvars, 1) == FAIL) {
+ 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.
@@ -3995,7 +4104,7 @@ int get_list_range(char **str, int *num1, int *num2)
*str = skipwhite((*str));
if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range
- vim_str2nr((char_u *)(*str), NULL, &len, 0, &num, NULL, 0, false);
+ vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false);
*str += len;
*num1 = (int)num;
first = true;
@@ -4003,7 +4112,7 @@ int get_list_range(char **str, int *num1, int *num2)
*str = skipwhite((*str));
if (**str == ',') { // parse "to" part of range
*str = skipwhite((*str) + 1);
- vim_str2nr((char_u *)(*str), NULL, &len, 0, &num, NULL, 0, false);
+ vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false);
if (len > 0) {
*num2 = (int)num;
*str = skipwhite((*str) + len);
@@ -4021,6 +4130,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 +4195,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 +4229,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--;
@@ -4111,7 +4248,7 @@ static int open_cmdwin(void)
i = 0;
}
if (get_histentry(histtype)[i].hisstr != NULL) {
- ml_append(lnum++, (char *)get_histentry(histtype)[i].hisstr, (colnr_T)0, false);
+ ml_append(lnum++, get_histentry(histtype)[i].hisstr, (colnr_T)0, false);
}
} while (i != *get_hisidx(histtype));
}
@@ -4119,7 +4256,7 @@ static int open_cmdwin(void)
// Replace the empty last line with the current command-line and put the
// cursor there.
- ml_replace(curbuf->b_ml.ml_line_count, (char *)ccline.cmdbuff, true);
+ ml_replace(curbuf->b_ml.ml_line_count, ccline.cmdbuff, true);
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
curwin->w_cursor.col = ccline.cmdpos;
changed_line_abv_curs();
@@ -4128,7 +4265,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;
@@ -4151,9 +4288,7 @@ static int open_cmdwin(void)
RedrawingDisabled = 0;
int save_count = save_batch_count();
- /*
- * Call the main loop until <CR> or CTRL-C is typed.
- */
+ // Call the main loop until <CR> or CTRL-C is typed.
normal_enter(true, false);
RedrawingDisabled = i;
@@ -4189,7 +4324,7 @@ static int open_cmdwin(void)
if (histtype == HIST_CMD) {
// Execute the command directly.
- ccline.cmdbuff = (char_u *)xstrdup(p);
+ ccline.cmdbuff = xstrdup(p);
cmdwin_result = CAR;
} else {
// First need to cancel what we were doing.
@@ -4203,10 +4338,10 @@ static int open_cmdwin(void)
// and don't modify the cmd window.
ccline.cmdbuff = NULL;
} else {
- ccline.cmdbuff = vim_strsave(get_cursor_line_ptr());
+ ccline.cmdbuff = xstrdup(get_cursor_line_ptr());
}
if (ccline.cmdbuff == NULL) {
- ccline.cmdbuff = vim_strsave((char_u *)"");
+ ccline.cmdbuff = xstrdup("");
ccline.cmdlen = 0;
ccline.cmdbufflen = 1;
ccline.cmdpos = 0;
diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h
index 5e3ad20a31..919a6c8f11 100644
--- a/src/nvim/ex_getln.h
+++ b/src/nvim/ex_getln.h
@@ -41,7 +41,7 @@ typedef enum {
/// structure.
typedef struct cmdline_info CmdlineInfo;
struct cmdline_info {
- char_u *cmdbuff; ///< pointer to command line buffer
+ char *cmdbuff; ///< pointer to command line buffer
int cmdbufflen; ///< length of cmdbuff
int cmdlen; ///< number of chars in command line
int cmdpos; ///< current cursor position
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..290d20b749 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -70,7 +70,8 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
|| kv_size(decor->virt_lines)
|| decor->conceal
|| decor_has_sign(decor)
- || decor->ui_watched) {
+ || decor->ui_watched
+ || decor->spell) {
decor_full = true;
decor = xmemdup(decor, sizeof *decor);
}
@@ -510,11 +511,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..b3491e98c2 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -69,17 +69,14 @@
#include "nvim/vim.h"
#include "nvim/window.h"
-static char_u *ff_expand_buffer = NULL; // used for expanding filenames
+static char *ff_expand_buffer = NULL; // used for expanding filenames
-/*
- * type for the directory search stack
- */
+// type for the directory search stack
typedef struct ff_stack {
struct ff_stack *ffs_prev;
- /* the fix part (no wildcards) and the part containing the wildcards
- * of the search path
- */
+ // the fix part (no wildcards) and the part containing the wildcards
+ // of the search path
char_u *ffs_fix_path;
char_u *ffs_wc_path;
@@ -89,98 +86,87 @@ typedef struct ff_stack {
int ffs_filearray_size;
int ffs_filearray_cur; // needed for partly handled dirs
- /* to store status of partly handled directories
- * 0: we work on this directory for the first time
- * 1: this directory was partly searched in an earlier step
- */
+ // to store status of partly handled directories
+ // 0: we work on this directory for the first time
+ // 1: this directory was partly searched in an earlier step
int ffs_stage;
- /* How deep are we in the directory tree?
- * Counts backward from value of level parameter to vim_findfile_init
- */
+ // How deep are we in the directory tree?
+ // Counts backward from value of level parameter to vim_findfile_init
int ffs_level;
// Did we already expand '**' to an empty string?
int ffs_star_star_empty;
} ff_stack_T;
-/*
- * type for already visited directories or files.
- */
+// type for already visited directories or files.
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.
- */
- char_u *ffv_wc_path;
+ // Visited directories are different if the wildcard string are
+ // different. So we have to save it.
+ char *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.
- */
- char_u ffv_fname[1]; // actually longer
+ // The memory for this struct is allocated according to the length of
+ // ffv_fname.
+ char ffv_fname[1]; // actually longer
} ff_visited_T;
-/*
- * We might have to manage several visited lists during a search.
- * This is especially needed for the tags option. If tags is set to:
- * "./++/tags,./++/TAGS,++/tags" (replace + with *)
- * So we have to do 3 searches:
- * 1) search from the current files directory downward for the file "tags"
- * 2) search from the current files directory downward for the file "TAGS"
- * 3) search from Vims current directory downwards for the file "tags"
- * As you can see, the first and the third search are for the same file, so for
- * the third search we can use the visited list of the first search. For the
- * second search we must start from an empty visited list.
- * The struct ff_visited_list_hdr is used to manage a linked list of already
- * visited lists.
- */
+// We might have to manage several visited lists during a search.
+// This is especially needed for the tags option. If tags is set to:
+// "./++/tags,./++/TAGS,++/tags" (replace + with *)
+// So we have to do 3 searches:
+// 1) search from the current files directory downward for the file "tags"
+// 2) search from the current files directory downward for the file "TAGS"
+// 3) search from Vims current directory downwards for the file "tags"
+// As you can see, the first and the third search are for the same file, so for
+// the third search we can use the visited list of the first search. For the
+// second search we must start from an empty visited list.
+// The struct ff_visited_list_hdr is used to manage a linked list of already
+// visited lists.
typedef struct ff_visited_list_hdr {
struct ff_visited_list_hdr *ffvl_next;
// the filename the attached visited list is for
- char_u *ffvl_filename;
+ char *ffvl_filename;
ff_visited_T *ffvl_visited_list;
} ff_visited_list_hdr_T;
-/*
- * '**' can be expanded to several directory levels.
- * Set the default maximum depth.
- */
+// '**' can be expanded to several directory levels.
+// Set the default maximum depth.
#define FF_MAX_STAR_STAR_EXPAND ((char_u)30)
-/*
- * The search context:
- * ffsc_stack_ptr: the stack for the dirs to search
- * ffsc_visited_list: the currently active visited list
- * ffsc_dir_visited_list: the currently active visited list for search dirs
- * ffsc_visited_lists_list: the list of all visited lists
- * ffsc_dir_visited_lists_list: the list of all visited lists for search dirs
- * ffsc_file_to_search: the file to search for
- * ffsc_start_dir: the starting directory, if search path was relative
- * ffsc_fix_path: the fix part of the given path (without wildcards)
- * Needed for upward search.
- * ffsc_wc_path: the part of the given path containing wildcards
- * ffsc_level: how many levels of dirs to search downwards
- * ffsc_stopdirs_v: array of stop directories for upward search
- * ffsc_find_what: FINDFILE_BOTH, FINDFILE_DIR or FINDFILE_FILE
- * ffsc_tagfile: searching for tags file, don't use 'suffixesadd'
- */
+// The search context:
+// ffsc_stack_ptr: the stack for the dirs to search
+// ffsc_visited_list: the currently active visited list
+// ffsc_dir_visited_list: the currently active visited list for search dirs
+// ffsc_visited_lists_list: the list of all visited lists
+// ffsc_dir_visited_lists_list: the list of all visited lists for search dirs
+// ffsc_file_to_search: the file to search for
+// ffsc_start_dir: the starting directory, if search path was relative
+// ffsc_fix_path: the fix part of the given path (without wildcards)
+// Needed for upward search.
+// ffsc_wc_path: the part of the given path containing wildcards
+// ffsc_level: how many levels of dirs to search downwards
+// ffsc_stopdirs_v: array of stop directories for upward search
+// ffsc_find_what: FINDFILE_BOTH, FINDFILE_DIR or FINDFILE_FILE
+// ffsc_tagfile: searching for tags file, don't use 'suffixesadd'
typedef struct ff_search_ctx_T {
ff_stack_T *ffsc_stack_ptr;
ff_visited_list_hdr_T *ffsc_visited_list;
ff_visited_list_hdr_T *ffsc_dir_visited_list;
ff_visited_list_hdr_T *ffsc_visited_lists_list;
ff_visited_list_hdr_T *ffsc_dir_visited_lists_list;
- char_u *ffsc_file_to_search;
- char_u *ffsc_start_dir;
- char_u *ffsc_fix_path;
- char_u *ffsc_wc_path;
+ char *ffsc_file_to_search;
+ char *ffsc_start_dir;
+ char *ffsc_fix_path;
+ char *ffsc_wc_path;
int ffsc_level;
- char_u **ffsc_stopdirs_v;
+ char **ffsc_stopdirs_v;
int ffsc_find_what;
int ffsc_tagfile;
} ff_search_ctx_T;
@@ -221,8 +207,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
@@ -246,17 +232,15 @@ static char_u e_pathtoolong[] = N_("E854: path too long for completion");
///
/// @param tagfile expanding names of tags files
/// @param rel_fname file name to use for "."
-void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int level,
- int free_visited, int find_what, void *search_ctx_arg, int tagfile,
- char_u *rel_fname)
+void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, int free_visited,
+ int find_what, void *search_ctx_arg, int tagfile, char *rel_fname)
{
- char_u *wc_part;
+ char *wc_part;
ff_stack_T *sptr;
ff_search_ctx_T *search_ctx;
- /* If a search context is given by the caller, reuse it, else allocate a
- * new one.
- */
+ // If a search context is given by the caller, reuse it, else allocate a
+ // new one.
if (search_ctx_arg != NULL) {
search_ctx = search_ctx_arg;
} else {
@@ -269,12 +253,12 @@ 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
- * filename. If no list for the current filename exists, creates a new
- * one. */
+ // Reuse old visited lists. Get the visited list for the given
+ // filename. If no list for the current filename exists, creates a new
+ // one.
search_ctx->ffsc_visited_list = ff_get_visited_list(filename,
&search_ctx->ffsc_visited_lists_list);
if (search_ctx->ffsc_visited_list == NULL) {
@@ -291,25 +275,25 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
ff_expand_buffer = xmalloc(MAXPATHL);
}
- /* Store information on starting dir now if path is relative.
- * If path is absolute, we do that later. */
+ // Store information on starting dir now if path is relative.
+ // If path is absolute, we do that later.
if (path[0] == '.'
&& (vim_ispathsep(path[1]) || path[1] == NUL)
&& (!tagfile || vim_strchr(p_cpo, CPO_DOTTAG) == NULL)
&& rel_fname != NULL) {
- size_t len = (size_t)((char_u *)path_tail((char *)rel_fname) - rel_fname);
+ size_t len = (size_t)(path_tail(rel_fname) - rel_fname);
- if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL) {
+ if (!vim_isAbsName((char_u *)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 = FullName_save(ff_expand_buffer, false);
} else {
- search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len);
+ search_ctx->ffsc_start_dir = xstrnsave(rel_fname, len);
}
if (*++path != NUL) {
path++;
}
- } else if (*path == NUL || !vim_isAbsName(path)) {
+ } else if (*path == NUL || !vim_isAbsName((char_u *)path)) {
#ifdef BACKSLASH_IN_FILENAME
// "c:dir" needs "c:" to be expanded, otherwise use current dir
if (*path != NUL && path[1] == ':') {
@@ -326,15 +310,15 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
path += 2;
} else
#endif
- if (os_dirname(ff_expand_buffer, MAXPATHL) == FAIL) {
+ if (os_dirname((char_u *)ff_expand_buffer, MAXPATHL) == FAIL) {
goto error_return;
}
- search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer);
+ search_ctx->ffsc_start_dir = xstrdup(ff_expand_buffer);
#ifdef BACKSLASH_IN_FILENAME
- /* A path that starts with "/dir" is relative to the drive, not to the
- * directory (but not for "//machine/dir"). Only use the drive name. */
+ // A path that starts with "/dir" is relative to the drive, not to the
+ // directory (but not for "//machine/dir"). Only use the drive name.
if ((*path == '/' || *path == '\\')
&& path[1] != path[0]
&& search_ctx->ffsc_start_dir[1] == ':') {
@@ -343,17 +327,15 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
#endif
}
- /*
- * If stopdirs are given, split them into an array of pointers.
- * If this fails (mem allocation), there is no upward search at all or a
- * stop directory is not recognized -> continue silently.
- * If stopdirs just contains a ";" or is empty,
- * search_ctx->ffsc_stopdirs_v will only contain a NULL pointer. This
- * is handled as unlimited upward search. See function
- * ff_path_in_stoplist() for details.
- */
+ // If stopdirs are given, split them into an array of pointers.
+ // If this fails (mem allocation), there is no upward search at all or a
+ // stop directory is not recognized -> continue silently.
+ // If stopdirs just contains a ";" or is empty,
+ // search_ctx->ffsc_stopdirs_v will only contain a NULL pointer. This
+ // is handled as unlimited upward search. See function
+ // ff_path_in_stoplist() for details.
if (stopdirs != NULL) {
- char_u *walker = stopdirs;
+ char *walker = stopdirs;
while (*walker == ';') {
walker++;
@@ -363,25 +345,21 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
search_ctx->ffsc_stopdirs_v = xmalloc(sizeof(char_u *));
do {
- char_u *helper;
+ char *helper;
void *ptr;
helper = walker;
ptr = xrealloc(search_ctx->ffsc_stopdirs_v,
(dircount + 1) * sizeof(char_u *));
search_ctx->ffsc_stopdirs_v = ptr;
- walker = (char_u *)vim_strchr((char *)walker, ';');
+ walker = vim_strchr(walker, ';');
if (walker) {
assert(walker - helper >= 0);
- search_ctx->ffsc_stopdirs_v[dircount - 1] =
- vim_strnsave(helper, (size_t)(walker - helper));
+ search_ctx->ffsc_stopdirs_v[dircount - 1] = xstrnsave(helper, (size_t)(walker - helper));
walker++;
} else {
- /* this might be "", which means ascent till top
- * of directory tree.
- */
- search_ctx->ffsc_stopdirs_v[dircount - 1] =
- vim_strsave(helper);
+ // this might be "", which means ascent till top of directory tree.
+ search_ctx->ffsc_stopdirs_v[dircount - 1] = xstrdup(helper);
}
dircount++;
@@ -391,11 +369,10 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
search_ctx->ffsc_level = level;
- /* split into:
- * -fix path
- * -wildcard_stuff (might be NULL)
- */
- wc_part = (char_u *)vim_strchr((char *)path, '*');
+ // split into:
+ // -fix path
+ // -wildcard_stuff (might be NULL)
+ wc_part = vim_strchr(path, '*');
if (wc_part != NULL) {
int64_t llevel;
int len;
@@ -403,17 +380,15 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
// save the fix part of the path
assert(wc_part - path >= 0);
- search_ctx->ffsc_fix_path = vim_strnsave(path, (size_t)(wc_part - path));
-
- /*
- * copy wc_path and add restricts to the '**' wildcard.
- * The octet after a '**' is used as a (binary) counter.
- * So '**3' is transposed to '**^C' ('^C' is ASCII value 3)
- * or '**76' is transposed to '**N'( 'N' is ASCII value 76).
- * If no restrict is given after '**' the default is used.
- * Due to this technique the path looks awful if you print it as a
- * string.
- */
+ search_ctx->ffsc_fix_path = xstrnsave(path, (size_t)(wc_part - path));
+
+ // copy wc_path and add restricts to the '**' wildcard.
+ // The octet after a '**' is used as a (binary) counter.
+ // So '**3' is transposed to '**^C' ('^C' is ASCII value 3)
+ // or '**76' is transposed to '**N'( 'N' is ASCII value 76).
+ // If no restrict is given after '**' the default is used.
+ // Due to this technique the path looks awful if you print it as a
+ // string.
len = 0;
while (*wc_part != NUL) {
if (len + 5 >= MAXPATHL) {
@@ -424,16 +399,16 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
ff_expand_buffer[len++] = *wc_part++;
ff_expand_buffer[len++] = *wc_part++;
- llevel = strtol((char *)wc_part, &errpt, 10);
- if ((char_u *)errpt != wc_part && llevel > 0 && llevel < 255) {
- ff_expand_buffer[len++] = (char_u)llevel;
- } else if ((char_u *)errpt != wc_part && llevel == 0) {
+ llevel = strtol(wc_part, &errpt, 10);
+ if (errpt != wc_part && llevel > 0 && llevel < 255) {
+ ff_expand_buffer[len++] = (char)llevel;
+ } else if (errpt != wc_part && llevel == 0) {
// restrict is 0 -> remove already added '**'
len -= 2;
} else {
ff_expand_buffer[len++] = FF_MAX_STAR_STAR_EXPAND;
}
- wc_part = (char_u *)errpt;
+ wc_part = errpt;
if (*wc_part != NUL && !vim_ispathsep(*wc_part)) {
semsg(_(
"E343: Invalid path: '**[number]' must be at the end of the path or be followed by '%s'."),
@@ -445,16 +420,15 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
}
}
ff_expand_buffer[len] = NUL;
- search_ctx->ffsc_wc_path = vim_strsave(ff_expand_buffer);
+ search_ctx->ffsc_wc_path = xstrdup(ff_expand_buffer);
} else {
- search_ctx->ffsc_fix_path = vim_strsave(path);
+ search_ctx->ffsc_fix_path = xstrdup(path);
}
if (search_ctx->ffsc_start_dir == NULL) {
- /* store the fix part as startdir.
- * This is needed if the parameter path is fully qualified.
- */
- search_ctx->ffsc_start_dir = vim_strsave(search_ctx->ffsc_fix_path);
+ // store the fix part as startdir.
+ // This is needed if the parameter path is fully qualified.
+ search_ctx->ffsc_start_dir = xstrdup(search_ctx->ffsc_fix_path);
search_ctx->ffsc_fix_path[0] = NUL;
}
@@ -465,20 +439,20 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
goto error_return;
}
STRCPY(ff_expand_buffer, search_ctx->ffsc_start_dir);
- add_pathsep((char *)ff_expand_buffer);
+ add_pathsep(ff_expand_buffer);
{
size_t eb_len = STRLEN(ff_expand_buffer);
char_u *buf = xmalloc(eb_len + STRLEN(search_ctx->ffsc_fix_path) + 1);
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);
+ add_pathsep(ff_expand_buffer);
} else {
- char_u *p = (char_u *)path_tail((char *)search_ctx->ffsc_fix_path);
- char_u *wc_path = NULL;
- char_u *temp = NULL;
+ char *p = path_tail(search_ctx->ffsc_fix_path);
+ char *wc_path = NULL;
+ char *temp = NULL;
int len = 0;
if (p > search_ctx->ffsc_fix_path) {
@@ -489,14 +463,14 @@ void *vim_findfile_init(char_u *path, char_u *filename, char_u *stopdirs, int le
xfree(buf);
goto error_return;
}
- STRLCAT(ff_expand_buffer, search_ctx->ffsc_fix_path, eb_len + (size_t)len + 1);
- add_pathsep((char *)ff_expand_buffer);
+ xstrlcat(ff_expand_buffer, search_ctx->ffsc_fix_path, eb_len + (size_t)len + 1);
+ add_pathsep(ff_expand_buffer);
} else {
len = (int)STRLEN(search_ctx->ffsc_fix_path);
}
if (search_ctx->ffsc_wc_path != NULL) {
- wc_path = vim_strsave(search_ctx->ffsc_wc_path);
+ wc_path = xstrdup(search_ctx->ffsc_wc_path);
temp = xmalloc(STRLEN(search_ctx->ffsc_wc_path)
+ STRLEN(search_ctx->ffsc_fix_path + len)
+ 1);
@@ -510,20 +484,16 @@ 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);
+ search_ctx->ffsc_file_to_search = xstrdup(filename);
return search_ctx;
error_return:
- /*
- * We clear the search context now!
- * Even when the caller gave us a (perhaps valid) context we free it here,
- * as we might have already destroyed it.
- */
+ // We clear the search context now!
+ // Even when the caller gave us a (perhaps valid) context we free it here,
+ // as we might have already destroyed it.
vim_findfile_cleanup(search_ctx);
return NULL;
}
@@ -535,8 +505,8 @@ char_u *vim_findfile_stopdir(char_u *buf)
while (*r_ptr != NUL && *r_ptr != ';') {
if (r_ptr[0] == '\\' && r_ptr[1] == ';') {
- /* Overwrite the escape char,
- * use STRLEN(r_ptr) to move the trailing '\0'. */
+ // Overwrite the escape char,
+ // use STRLEN(r_ptr) to move the trailing '\0'.
STRMOVE(r_ptr, r_ptr + 1);
r_ptr++;
}
@@ -593,16 +563,13 @@ char_u *vim_findfile(void *search_ctx_arg)
search_ctx = (ff_search_ctx_T *)search_ctx_arg;
- /*
- * filepath is used as buffer for various actions and as the storage to
- * return a found filename.
- */
+ // filepath is used as buffer for various actions and as the storage to
+ // return a found filename.
file_path = xmalloc(MAXPATHL);
// store the end of the start dir -- needed for upward search
if (search_ctx->ffsc_start_dir != NULL) {
- path_end = &search_ctx->ffsc_start_dir[
- STRLEN(search_ctx->ffsc_start_dir)];
+ path_end = (char_u *)&search_ctx->ffsc_start_dir[STRLEN(search_ctx->ffsc_start_dir)];
}
// upward search loop
@@ -621,31 +588,26 @@ char_u *vim_findfile(void *search_ctx_arg)
break;
}
- /*
- * TODO: decide if we leave this test in
- *
- * GOOD: don't search a directory(-tree) twice.
- * BAD: - check linked list for every new directory entered.
- * - check for double files also done below
- *
- * Here we check if we already searched this directory.
- * We already searched a directory if:
- * 1) The directory is the same.
- * 2) We would use the same wildcard string.
- *
- * Good if you have links on same directory via several ways
- * or you have selfreferences in directories (e.g. SuSE Linux 6.3:
- * /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop)
- *
- * This check is only needed for directories we work on for the
- * first time (hence stackp->ff_filearray == NULL)
- */
+ // TODO(vim): decide if we leave this test in
+ //
+ // GOOD: don't search a directory(-tree) twice.
+ // BAD: - check linked list for every new directory entered.
+ // - check for double files also done below
+ //
+ // Here we check if we already searched this directory.
+ // We already searched a directory if:
+ // 1) The directory is the same.
+ // 2) We would use the same wildcard string.
+ //
+ // Good if you have links on same directory via several ways
+ // or you have selfreferences in directories (e.g. SuSE Linux 6.3:
+ // /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop)
+ //
+ // This check is only needed for directories we work on for the
+ // 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,
+ (char *)stackp->ffs_fix_path, (char *)stackp->ffs_wc_path) == FAIL) {
#ifdef FF_VERBOSE
if (p_verbose >= 5) {
verbose_enter_scroll();
@@ -676,18 +638,14 @@ char_u *vim_findfile(void *search_ctx_arg)
file_path[0] = NUL;
- /*
- * If no filearray till now expand wildcards
- * The function expand_wildcards() can handle an array of paths
- * and all possible expands are returned in one array. We use this
- * to handle the expansion of '**' into an empty string.
- */
+ // If no filearray till now expand wildcards
+ // The function expand_wildcards() can handle an array of paths
+ // and all possible expands are returned in one array. We use this
+ // to handle the expansion of '**' into an empty string.
if (stackp->ffs_filearray == NULL) {
char *dirptrs[2];
- /* we use filepath to build the path expand_wildcards() should
- * expand.
- */
+ // we use filepath to build the path expand_wildcards() should expand.
dirptrs[0] = (char *)file_path;
dirptrs[1] = NULL;
@@ -747,13 +705,11 @@ char_u *vim_findfile(void *search_ctx_arg)
}
}
- /*
- * Here we copy until the next path separator or the end of
- * the path. If we stop at a path separator, there is
- * still something else left. This is handled below by
- * pushing every directory returned from expand_wildcards()
- * on the stack again for further search.
- */
+ // Here we copy until the next path separator or the end of
+ // the path. If we stop at a path separator, there is
+ // still something else left. This is handled below by
+ // pushing every directory returned from expand_wildcards()
+ // on the stack again for further search.
while (*rest_of_wildcards
&& !vim_ispathsep(*rest_of_wildcards)) {
if (len + 1 >= MAXPATHL) {
@@ -769,18 +725,16 @@ char_u *vim_findfile(void *search_ctx_arg)
}
}
- /*
- * Expand wildcards like "*" and "$VAR".
- * If the path is a URL don't try this.
- */
+ // Expand wildcards like "*" and "$VAR".
+ // If the path is a URL don't try this.
if (path_with_url(dirptrs[0])) {
stackp->ffs_filearray = xmalloc(sizeof(char *));
stackp->ffs_filearray[0] = xstrdup(dirptrs[0]);
stackp->ffs_filearray_size = 1;
} else {
- /* Add EW_NOTWILD because the expanded path may contain
- * wildcard characters that are to be taken literally.
- * This is a bit of a hack. */
+ // Add EW_NOTWILD because the expanded path may contain
+ // wildcard characters that are to be taken literally.
+ // This is a bit of a hack.
expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs,
&stackp->ffs_filearray_size,
&stackp->ffs_filearray,
@@ -790,20 +744,17 @@ 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) {
// this is the first time we work on this directory
if (*rest_of_wildcards == NUL) {
- /*
- * We don't have further wildcards to expand, so we have to
- * check for the final file now.
- */
+ // We don't have further wildcards to expand, so we have to
+ // check for the final file now.
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
@@ -819,37 +770,29 @@ char_u *vim_findfile(void *search_ctx_arg)
}
STRCAT(file_path, search_ctx->ffsc_file_to_search);
- /*
- * Try without extra suffix and then with suffixes
- * from 'suffixesadd'.
- */
+ // Try without extra suffix and then with suffixes
+ // from 'suffixesadd'.
len = STRLEN(file_path);
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)))))
+ || (os_path_exists((char *)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)
+ (char *)file_path, "") == 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);
@@ -868,10 +811,9 @@ char_u *vim_findfile(void *search_ctx_arg)
if (!path_with_url((char *)file_path)) {
simplify_filename(file_path);
}
- if (os_dirname(ff_expand_buffer, MAXPATHL)
+ if (os_dirname((char_u *)ff_expand_buffer, MAXPATHL)
== OK) {
- p = path_shorten_fname(file_path,
- ff_expand_buffer);
+ p = (char_u *)path_shorten_fname((char *)file_path, ff_expand_buffer);
if (p != NULL) {
STRMOVE(file_path, p);
}
@@ -898,12 +840,12 @@ 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,
- ff_create_stack_element((char_u *)stackp->ffs_filearray[i],
- rest_of_wildcards,
+ ff_create_stack_element(stackp->ffs_filearray[i],
+ (char *)rest_of_wildcards,
stackp->ffs_level - 1, 0));
}
}
@@ -911,23 +853,21 @@ char_u *vim_findfile(void *search_ctx_arg)
stackp->ffs_stage = 1;
}
- /*
- * if wildcards contains '**' we have to descent till we reach the
- * leaves of the directory tree.
- */
+ // if wildcards contains '**' we have to descent till we reach the
+ // leaves of the directory tree.
if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0) {
for (int i = stackp->ffs_filearray_cur;
i < stackp->ffs_filearray_size; i++) {
- if (FNAMECMP(stackp->ffs_filearray[i],
- stackp->ffs_fix_path) == 0) {
+ if (path_fnamecmp(stackp->ffs_filearray[i],
+ (char *)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,
- ff_create_stack_element((char_u *)stackp->ffs_filearray[i],
- stackp->ffs_wc_path, stackp->ffs_level - 1, 1));
+ ff_create_stack_element(stackp->ffs_filearray[i],
+ (char *)stackp->ffs_wc_path, stackp->ffs_level - 1, 1));
}
}
@@ -935,27 +875,24 @@ char_u *vim_findfile(void *search_ctx_arg)
ff_free_stack_element(stackp);
}
- /* If we reached this, we didn't find anything downwards.
- * Let's check if we should do an upward search.
- */
+ // If we reached this, we didn't find anything downwards.
+ // Let's check if we should do an upward search.
if (search_ctx->ffsc_start_dir
&& search_ctx->ffsc_stopdirs_v != NULL && !got_int) {
ff_stack_T *sptr;
// 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) {
+ (int)(path_end - (char_u *)search_ctx->ffsc_start_dir),
+ search_ctx->ffsc_stopdirs_v) == true) {
break;
}
// cut of last dir
- while (path_end > search_ctx->ffsc_start_dir
- && vim_ispathsep(*path_end)) {
+ while (path_end > (char_u *)search_ctx->ffsc_start_dir && vim_ispathsep(*path_end)) {
path_end--;
}
- while (path_end > search_ctx->ffsc_start_dir
- && !vim_ispathsep(path_end[-1])) {
+ while (path_end > (char_u *)search_ctx->ffsc_start_dir && !vim_ispathsep(path_end[-1])) {
path_end--;
}
*path_end = 0;
@@ -976,7 +913,7 @@ char_u *vim_findfile(void *search_ctx_arg)
STRCAT(file_path, search_ctx->ffsc_fix_path);
// create a new stack entry
- sptr = ff_create_stack_element(file_path,
+ sptr = ff_create_stack_element((char *)file_path,
search_ctx->ffsc_wc_path, search_ctx->ffsc_level, 0);
ff_push(search_ctx, sptr);
} else {
@@ -1034,7 +971,7 @@ static void ff_free_visited_list(ff_visited_T *vl)
/// @return the already visited list for the given filename. If none is found it
/// allocates a new one.
-static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename,
+static ff_visited_list_hdr_T *ff_get_visited_list(char *filename,
ff_visited_list_hdr_T **list_headp)
{
ff_visited_list_hdr_T *retptr = NULL;
@@ -1043,7 +980,7 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename,
if (*list_headp != NULL) {
retptr = *list_headp;
while (retptr != NULL) {
- if (FNAMECMP(filename, retptr->ffvl_filename) == 0) {
+ if (path_fnamecmp(filename, retptr->ffvl_filename) == 0) {
#ifdef FF_VERBOSE
if (p_verbose >= 5) {
verbose_enter_scroll();
@@ -1067,13 +1004,11 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename,
}
#endif
- /*
- * if we reach this we didn't find a list and we have to allocate new list
- */
+ // if we reach this we didn't find a list and we have to allocate new list
retptr = xmalloc(sizeof(*retptr));
retptr->ffvl_visited_list = NULL;
- retptr->ffvl_filename = vim_strsave(filename);
+ retptr->ffvl_filename = xstrdup(filename);
retptr->ffvl_next = *list_headp;
*list_headp = retptr;
@@ -1124,7 +1059,7 @@ static bool ff_wc_equal(char_u *s1, char_u *s2)
///
/// @return FAIL if the given file/dir is already in the list or,
/// OK if it is newly added
-static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *wc_path)
+static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_path)
{
ff_visited_T *vp;
bool url = false;
@@ -1132,32 +1067,30 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *
FileID file_id;
// For a URL we only compare the name, otherwise we compare the
// device/inode.
- if (path_with_url((char *)fname)) {
+ if (path_with_url(fname)) {
STRLCPY(ff_expand_buffer, fname, MAXPATHL);
url = true;
} else {
ff_expand_buffer[0] = NUL;
- if (!os_fileid((char *)fname, &file_id)) {
+ if (!os_fileid(fname, &file_id)) {
return FAIL;
}
}
// check against list of already visited files
for (vp = *visited_list; vp != NULL; vp = vp->ffv_next) {
- if ((url && FNAMECMP(vp->ffv_fname, ff_expand_buffer) == 0)
+ if ((url && path_fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0)
|| (!url && vp->file_id_valid
&& os_fileid_equal(&(vp->file_id), &file_id))) {
// are the wildcard parts equal
- if (ff_wc_equal(vp->ffv_wc_path, wc_path)) {
+ if (ff_wc_equal((char_u *)vp->ffv_wc_path, (char_u *)wc_path)) {
// already visited
return FAIL;
}
}
}
- /*
- * New file/dir. Add it to the list of visited files/dirs.
- */
+ // New file/dir. Add it to the list of visited files/dirs.
vp = xmalloc(sizeof(ff_visited_T) + STRLEN(ff_expand_buffer));
if (!url) {
@@ -1170,7 +1103,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *
}
if (wc_path != NULL) {
- vp->ffv_wc_path = vim_strsave(wc_path);
+ vp->ffv_wc_path = xstrdup(wc_path);
} else {
vp->ffv_wc_path = NULL;
}
@@ -1182,7 +1115,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *
}
/// create stack element from given path pieces
-static ff_stack_T *ff_create_stack_element(char_u *fix_part, char_u *wc_part, int level,
+static ff_stack_T *ff_create_stack_element(char *fix_part, char *wc_part, int level,
int star_star_empty)
{
ff_stack_T *new = xmalloc(sizeof(ff_stack_T));
@@ -1197,14 +1130,14 @@ static ff_stack_T *ff_create_stack_element(char_u *fix_part, char_u *wc_part, in
// the following saves NULL pointer checks in vim_findfile
if (fix_part == NULL) {
- fix_part = (char_u *)"";
+ fix_part = "";
}
- new->ffs_fix_path = vim_strsave(fix_part);
+ new->ffs_fix_path = (char_u *)xstrdup(fix_part);
if (wc_part == NULL) {
- wc_part = (char_u *)"";
+ wc_part = "";
}
- new->ffs_wc_path = vim_strsave(wc_part);
+ new->ffs_wc_path = (char_u *)xstrdup(wc_part);
return new;
}
@@ -1212,8 +1145,8 @@ static ff_stack_T *ff_create_stack_element(char_u *fix_part, char_u *wc_part, in
/// Push a dir on the directory stack.
static void ff_push(ff_search_ctx_T *search_ctx, ff_stack_T *stack_ptr)
{
- /* check for NULL pointer, not to return an error to the user, but
- * to prevent a crash */
+ // check for NULL pointer, not to return an error to the user, but
+ // to prevent a crash
if (stack_ptr != NULL) {
stack_ptr->ffs_prev = search_ctx->ffsc_stack_ptr;
search_ctx->ffsc_stack_ptr = stack_ptr;
@@ -1289,8 +1222,8 @@ 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
-static int ff_path_in_stoplist(char_u *path, int path_len, char_u **stopdirs_v)
+/// @return true if yes else false
+static int ff_path_in_stoplist(char *path, int path_len, char **stopdirs_v)
{
int i = 0;
@@ -1301,32 +1234,31 @@ 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++) {
if ((int)STRLEN(stopdirs_v[i]) > path_len) {
- /* match for parent directory. So '/home' also matches
- * '/home/rks'. Check for PATHSEP in stopdirs_v[i], else
- * '/home/r' would also match '/home/rks'
- */
- if (FNAMENCMP(stopdirs_v[i], path, path_len) == 0
+ // match for parent directory. So '/home' also matches
+ // '/home/rks'. Check for PATHSEP in stopdirs_v[i], else
+ // '/home/r' would also match '/home/rks'
+ if (path_fnamencmp(stopdirs_v[i], path, (size_t)path_len) == 0
&& vim_ispathsep(stopdirs_v[i][path_len])) {
- return TRUE;
+ return true;
}
} else {
- if (FNAMECMP(stopdirs_v[i], path) == 0) {
+ if (path_fnamecmp(stopdirs_v[i], path) == 0) {
return true;
}
}
}
- 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,11 +1287,11 @@ 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;
+static char *ff_file_to_find = NULL;
static void *fdip_search_ctx = NULL;
#if defined(EXITFREE)
@@ -1387,7 +1319,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 *)"");
}
@@ -1405,7 +1337,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
static char *dir;
static int did_findfile_init = false;
char_u save_char;
- char_u *file_name = NULL;
+ char *file_name = NULL;
char *buf = NULL;
int rel_to_curdir;
@@ -1422,14 +1354,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 = xstrdup(NameBuff);
if (options & FNAME_UNESC) {
// Change all "\ " to " ".
- for (ptr = ff_file_to_find; *ptr != NUL; ++ptr) {
+ for (ptr = (char_u *)ff_file_to_find; *ptr != NUL; ptr++) {
if (ptr[0] == '\\' && ptr[1] == ' ') {
memmove(ptr, ptr + 1, STRLEN(ptr));
}
@@ -1443,7 +1375,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
|| (ff_file_to_find[1] == '.'
&& (ff_file_to_find[2] == NUL
|| vim_ispathsep(ff_file_to_find[2])))));
- if (vim_isAbsName(ff_file_to_find)
+ if (vim_isAbsName((char_u *)ff_file_to_find)
// "..", "../path", "." and "./path": don't use the path_option
|| rel_to_curdir
#if defined(WIN32)
@@ -1453,20 +1385,18 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
|| (ff_file_to_find[0] != NUL && ff_file_to_find[1] == ':')
#endif
) {
- /*
- * Absolute path, no need to use "path_option".
- * If this is not a first call, return NULL. We already returned a
- * filename on the first call.
- */
- if (first == TRUE) {
- if (path_with_url((char *)ff_file_to_find)) {
- file_name = vim_strsave(ff_file_to_find);
+ // Absolute path, no need to use "path_option".
+ // If this is not a first call, return NULL. We already returned a
+ // filename on the first call.
+ if (first == true) {
+ if (path_with_url(ff_file_to_find)) {
+ file_name = xstrdup(ff_file_to_find);
goto theend;
}
- /* 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) {
+ // 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++) {
size_t l = STRLEN(ff_file_to_find);
if (run == 1
&& rel_to_curdir
@@ -1481,8 +1411,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
run = 2;
}
- /* When the file doesn't exist, try adding parts of
- * 'suffixesadd'. */
+ // When the file doesn't exist, try adding parts of 'suffixesadd'.
buf = (char *)suffixes;
for (;;) {
if (
@@ -1490,7 +1419,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
&& (find_what == FINDFILE_BOTH
|| ((find_what == FINDFILE_DIR)
== os_isdir(NameBuff))))) {
- file_name = vim_strsave(NameBuff);
+ file_name = xstrdup(NameBuff);
goto theend;
}
if (*buf == NUL) {
@@ -1502,12 +1431,10 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
}
}
} else {
- /*
- * Loop over all paths in the 'path' or 'cdpath' option.
- * When "first" is set, first setup to the start of the option.
- * Otherwise continue to find the next match.
- */
- if (first == TRUE) {
+ // Loop over all paths in the 'path' or 'cdpath' option.
+ // When "first" is set, first setup to the start of the option.
+ // Otherwise continue to find the next match.
+ if (first == true) {
// vim_findfile_free_visited can handle a possible NULL pointer
vim_findfile_free_visited(fdip_search_ctx);
dir = (char *)path_option;
@@ -1516,18 +1443,17 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
for (;;) {
if (did_findfile_init) {
- file_name = vim_findfile(fdip_search_ctx);
+ file_name = (char *)vim_findfile(fdip_search_ctx);
if (file_name != NULL) {
break;
}
- did_findfile_init = FALSE;
+ did_findfile_init = false;
} else {
char_u *r_ptr;
if (dir == NULL || *dir == NUL) {
- /* We searched all paths of the option, now we can
- * free the search context. */
+ // We searched all paths of the option, now we can free the search context.
vim_findfile_cleanup(fdip_search_ctx);
fdip_search_ctx = NULL;
break;
@@ -1541,18 +1467,18 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
// get the stopdir string
r_ptr = vim_findfile_stopdir((char_u *)buf);
- fdip_search_ctx = vim_findfile_init((char_u *)buf, ff_file_to_find,
- r_ptr, 100, false, find_what,
- fdip_search_ctx, false, rel_fname);
+ fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find,
+ (char *)r_ptr, 100, false, find_what,
+ fdip_search_ctx, false, (char *)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);
@@ -1572,7 +1498,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
}
theend:
- return file_name;
+ return (char_u *)file_name;
}
void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause, bool pre)
@@ -1654,7 +1580,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..0bc7f736bc 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -82,17 +82,15 @@
#define FIO_UCSBOM 0x4000 // check for BOM at start of file
#define FIO_ALL (-1) // allow all formats
-/* When converting, a read() or write() may leave some bytes to be converted
- * for the next call. The value is guessed... */
+// When converting, a read() or write() may leave some bytes to be converted
+// for the next call. The value is guessed...
#define CONV_RESTLEN 30
-/* We have to guess how much a sequence of bytes may expand when converting
- * with iconv() to be able to allocate a buffer. */
+// We have to guess how much a sequence of bytes may expand when converting
+// with iconv() to be able to allocate a buffer.
#define ICONV_MULT 8
-/*
- * Structure to pass arguments from buf_write() to buf_write_bytes().
- */
+// Structure to pass arguments from buf_write() to buf_write_bytes().
struct bw_info {
int bw_fd; // file descriptor
char_u *bw_buf; // buffer with data to be written
@@ -119,7 +117,7 @@ struct bw_info {
static char *e_auchangedbuf = N_("E812: Autocommands changed buffer or buffer name");
-void filemess(buf_T *buf, char_u *name, char_u *s, int attr)
+void filemess(buf_T *buf, char *name, char *s, int attr)
{
int msg_scroll_save;
@@ -128,13 +126,13 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr)
}
add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)name);
// Avoid an over-long translation to cause trouble.
- STRLCAT(IObuff, s, IOSIZE);
+ xstrlcat(IObuff, s, IOSIZE);
// For the first message may have to start a new line.
// For further ones overwrite the previous one, reset msg_scroll before
// calling filemess().
msg_scroll_save = msg_scroll;
if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0) {
- msg_scroll = FALSE;
+ msg_scroll = false;
}
if (!msg_scroll) { // wait a bit when overwriting an error msg
check_for_delay(false);
@@ -143,7 +141,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(msg_may_trunc(false, (char *)IObuff), attr);
msg_clr_eos();
ui_flush();
msg_scrolled_ign = false;
@@ -167,6 +165,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
@@ -256,12 +255,10 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
curbuf->b_no_eol_lnum = 0; // in case it was set by the previous read
- /*
- * If there is no file name yet, use the one for the read file.
- * BF_NOTEDITED is set to reflect this.
- * Don't do this for a read from a filter.
- * Only do this when 'cpoptions' contains the 'f' flag.
- */
+ // If there is no file name yet, use the one for the read file.
+ // BF_NOTEDITED is set to reflect this.
+ // Don't do this for a read from a filter.
+ // Only do this when 'cpoptions' contains the 'f' flag.
if (curbuf->b_ffname == NULL
&& !filtering
&& fname != NULL
@@ -334,12 +331,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) {
@@ -347,7 +350,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
// If the name is too long we might crash further on, quit here.
if (namelen >= MAXPATHL) {
- filemess(curbuf, (char_u *)fname, (char_u *)_("Illegal file name"), 0);
+ filemess(curbuf, fname, _("Illegal file name"), 0);
msg_end();
msg_scroll = msg_save;
return FAIL;
@@ -358,7 +361,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
// swap file may destroy it! Reported on MS-DOS and Win 95.
if (after_pathsep(fname, fname + namelen)) {
if (!silent) {
- filemess(curbuf, (char_u *)fname, (char_u *)_(msg_is_a_directory), 0);
+ filemess(curbuf, fname, _(msg_is_a_directory), 0);
}
msg_end();
msg_scroll = msg_save;
@@ -380,10 +383,10 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
) {
if (S_ISDIR(perm)) {
if (!silent) {
- filemess(curbuf, (char_u *)fname, (char_u *)_(msg_is_a_directory), 0);
+ filemess(curbuf, fname, _(msg_is_a_directory), 0);
}
} else {
- filemess(curbuf, (char_u *)fname, (char_u *)_("is not a file"), 0);
+ filemess(curbuf, fname, _("is not a file"), 0);
}
msg_end();
msg_scroll = msg_save;
@@ -394,15 +397,13 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
// Set default or forced 'fileformat' and 'binary'.
set_file_options(set_options, eap);
- /*
- * When opening a new file we take the readonly flag from the file.
- * Default is r/w, can be set to r/o below.
- * Don't reset it when in readonly mode
- * Only set/reset b_p_ro when BF_CHECK_RO is set.
- */
+ // When opening a new file we take the readonly flag from the file.
+ // Default is r/w, can be set to r/o below.
+ // Don't reset it when in readonly mode
+ // Only set/reset b_p_ro when BF_CHECK_RO is set.
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) {
@@ -412,17 +413,15 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
curbuf->b_mtime_read = curbuf->b_mtime;
curbuf->b_mtime_read_ns = curbuf->b_mtime_ns;
#ifdef UNIX
- /*
- * Use the protection bits of the original file for the swap file.
- * This makes it possible for others to read the name of the
- * edited file from the swapfile, but only if they can read the
- * edited file.
- * Remove the "write" and "execute" bits for group and others
- * (they must not write the swapfile).
- * Add the "read" and "write" bits for the user, otherwise we may
- * not be able to write to the file ourselves.
- * Setting the bits is done below, after creating the swap file.
- */
+ // Use the protection bits of the original file for the swap file.
+ // This makes it possible for others to read the name of the
+ // edited file from the swapfile, but only if they can read the
+ // edited file.
+ // Remove the "write" and "execute" bits for group and others
+ // (they must not write the swapfile).
+ // Add the "read" and "write" bits for the user, otherwise we may
+ // not be able to write to the file ourselves.
+ // Setting the bits is done below, after creating the swap file.
swap_mode = ((int)file_info.stat.st_mode & 0644) | 0600;
#endif
} else {
@@ -476,9 +475,9 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
}
if (!silent) {
if (dir_of_file_exists((char_u *)fname)) {
- filemess(curbuf, (char_u *)sfname, (char_u *)new_file_message(), 0);
+ filemess(curbuf, sfname, new_file_message(), 0);
} else {
- filemess(curbuf, (char_u *)sfname, (char_u *)_("[New DIRECTORY]"), 0);
+ filemess(curbuf, sfname, _("[New DIRECTORY]"), 0);
}
}
// Even though this is a new file, it might have been
@@ -498,38 +497,36 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
}
return OK; // a new file is not an error
} else {
- filemess(curbuf, (char_u *)sfname, (char_u *)((fd == UV_EFBIG) ? _("[File too big]") :
+ filemess(curbuf, sfname, ((fd == UV_EFBIG) ? _("[File too big]") :
#if defined(UNIX) && defined(EOVERFLOW)
- // libuv only returns -errno
- // in Unix and in Windows
- // open() does not set
- // EOVERFLOW
- (fd == -EOVERFLOW) ? _("[File too big]") :
+ // libuv only returns -errno
+ // in Unix and in Windows
+ // open() does not set
+ // EOVERFLOW
+ (fd == -EOVERFLOW) ? _("[File too big]") :
#endif
- _("[Permission Denied]")), 0);
+ _("[Permission Denied]")), 0);
curbuf->b_p_ro = true; // must use "w!" now
}
return FAIL;
}
- /*
- * Only set the 'ro' flag for readonly files the first time they are
- * loaded. Help files always get readonly mode
- */
+ // Only set the 'ro' flag for readonly files the first time they are
+ // 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 +580,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,16 +632,14 @@ 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;
}
- /*
- * Don't allow the autocommands to change the current buffer.
- * Try to re-open the file.
- *
- * Don't allow the autocommands to change the buffer name either
- * (cd for example) if it invalidates fname or sfname.
- */
+ // Don't allow the autocommands to change the current buffer.
+ // Try to re-open the file.
+ //
+ // Don't allow the autocommands to change the buffer name either
+ // (cd for example) if it invalidates fname or sfname.
if (!read_stdin && (curbuf != old_curbuf
|| (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
|| (using_b_fname && (old_b_fname != curbuf->b_fname))
@@ -656,7 +651,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;
}
}
@@ -666,16 +661,14 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
if (!recoverymode && !filtering && !(flags & READ_DUMMY) && !silent) {
if (!read_stdin && !read_buffer) {
- filemess(curbuf, (char_u *)sfname, (char_u *)"", 0);
+ filemess(curbuf, sfname, "", 0);
}
}
- 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
- * fileformat, and after the autocommands, which may change them.
- */
+ // Set linecnt now, before the "retry" caused by a wrong guess for
+ // fileformat, and after the autocommands, which may change them.
linecnt = curbuf->b_ml.ml_line_count;
// "++bad=" argument.
@@ -688,11 +681,9 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
curbuf->b_bad_char = 0;
}
- /*
- * Decide which 'encoding' to use or use first.
- */
+ // 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,32 +699,30 @@ 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 = (char *)next_fenc(&fenc_next, &fenc_alloced);
- }
-
- /*
- * Jump back here to retry reading the file in different ways.
- * Reasons to retry:
- * - encoding conversion failed: try another one from "fenc_next"
- * - BOM detected and fenc was set, need to setup conversion
- * - "fileformat" check failed: try another
- *
- * Variables set for special retry actions:
- * "file_rewind" Rewind the file to start reading it again.
- * "advance_fenc" Advance "fenc" using "fenc_next".
- * "skip_read" Re-use already read bytes (BOM detected).
- * "did_iconv" iconv() conversion failed, try 'charconvert'.
- * "keep_fileformat" Don't reset "fileformat".
- *
- * Other status indicators:
- * "tmpname" When != NULL did conversion with 'charconvert'.
- * Output file has to be deleted afterwards.
- * "iconv_fd" When != -1 did conversion with iconv().
- */
+ fenc_next = p_fencs; // try items in 'fileencodings'
+ fenc = next_fenc(&fenc_next, &fenc_alloced);
+ }
+
+ // Jump back here to retry reading the file in different ways.
+ // Reasons to retry:
+ // - encoding conversion failed: try another one from "fenc_next"
+ // - BOM detected and fenc was set, need to setup conversion
+ // - "fileformat" check failed: try another
+ //
+ // Variables set for special retry actions:
+ // "file_rewind" Rewind the file to start reading it again.
+ // "advance_fenc" Advance "fenc" using "fenc_next".
+ // "skip_read" Re-use already read bytes (BOM detected).
+ // "did_iconv" iconv() conversion failed, try 'charconvert'.
+ // "keep_fileformat" Don't reset "fileformat".
+ //
+ // Other status indicators:
+ // "tmpname" When != NULL did conversion with 'charconvert'.
+ // Output file has to be deleted afterwards.
+ // "iconv_fd" When != -1 did conversion with iconv().
retry:
if (file_rewind) {
@@ -751,22 +740,20 @@ 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;
}
- /*
- * When retrying with another "fenc" and the first time "fileformat"
- * will be reset.
- */
+ // When retrying with another "fenc" and the first time "fileformat"
+ // will be reset.
if (keep_fileformat) {
keep_fileformat = false;
} 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 ==
@@ -786,9 +773,7 @@ retry:
#endif
if (advance_fenc) {
- /*
- * Try the next entry in 'fileencodings'.
- */
+ // Try the next entry in 'fileencodings'.
advance_fenc = false;
if (eap != NULL && eap->force_enc != 0) {
@@ -806,7 +791,7 @@ retry:
xfree(fenc);
}
if (fenc_next != NULL) {
- fenc = (char *)next_fenc(&fenc_next, &fenc_alloced);
+ fenc = next_fenc(&fenc_next, &fenc_alloced);
} else {
fenc = "";
fenc_alloced = false;
@@ -818,16 +803,14 @@ retry:
}
}
- /*
- * Conversion may be required when the encoding of the file is different
- * from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4.
- */
+ // Conversion may be required when the encoding of the file is different
+ // from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4.
fio_flags = 0;
- converted = need_conversion((char_u *)fenc);
+ converted = need_conversion(fenc);
if (converted) {
// "ucs-bom" means we need to check the first bytes of the file
// for a BOM.
- if (STRCMP(fenc, ENC_UCSBOM) == 0) {
+ if (strcmp(fenc, ENC_UCSBOM) == 0) {
fio_flags = FIO_UCSBOM;
} else {
// Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be
@@ -848,10 +831,8 @@ retry:
}
#endif
- /*
- * Use the 'charconvert' expression when conversion is required
- * and we can't do it internally or with iconv().
- */
+ // Use the 'charconvert' expression when conversion is required
+ // and we can't do it internally or with iconv().
if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
&& !read_fifo
#ifdef HAVE_ICONV
@@ -892,7 +873,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);
@@ -915,12 +896,10 @@ retry:
}
while (!error && !got_int) {
- /*
- * We allocate as much space for the file as we can get, plus
- * space for the old line plus room for one terminating NUL.
- * The amount is limited by the fact that read() only can read
- * up to max_unsigned characters (and other things).
- */
+ // We allocate as much space for the file as we can get, plus
+ // space for the old line plus room for one terminating NUL.
+ // The amount is limited by the fact that read() only can read
+ // up to max_unsigned characters (and other things).
{
if (!skip_read) {
// Use buffer >= 64K. Add linerest to double the size if the
@@ -992,10 +971,8 @@ retry:
}
if (read_buffer) {
- /*
- * Read bytes from curbuf. Used for converting text read
- * from stdin.
- */
+ // Read bytes from curbuf. Used for converting text read
+ // from stdin.
if (read_buf_lnum > from) {
size = 0;
} else {
@@ -1004,14 +981,14 @@ retry:
tlen = 0;
for (;;) {
- p = ml_get(read_buf_lnum) + read_buf_col;
+ p = (char_u *)ml_get(read_buf_lnum) + read_buf_col;
n = (int)STRLEN(p);
if ((int)tlen + n + 1 > size) {
// Filled up to "size", append partial line.
// 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 {
@@ -1045,9 +1022,7 @@ retry:
}
}
} else {
- /*
- * Read bytes from the file.
- */
+ // Read bytes from the file.
size = read_eintr(fd, ptr, (size_t)size);
}
@@ -1055,10 +1030,8 @@ retry:
if (size < 0) { // read error
error = true;
} else if (conv_restlen > 0) {
- /*
- * Reached end-of-file but some trailing bytes could
- * not be converted. Truncated file?
- */
+ // Reached end-of-file but some trailing bytes could
+ // not be converted. Truncated file?
// When we did a conversion report an error.
if (fio_flags != 0
@@ -1111,12 +1084,10 @@ retry:
skip_read = false;
- /*
- * At start of file: Check for BOM.
- * Also check for a BOM for other Unicode encodings, but not after
- * converting with 'charconvert' or when a BOM has already been
- * found.
- */
+ // At start of file: Check for BOM.
+ // Also check for a BOM for other Unicode encodings, but not after
+ // converting with 'charconvert' or when a BOM has already been
+ // found.
if ((filesize == 0)
&& (fio_flags == FIO_UCSBOM
|| (!curbuf->b_p_bomb
@@ -1138,8 +1109,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;
}
}
@@ -1165,9 +1136,7 @@ retry:
ptr -= conv_restlen;
size += conv_restlen;
conv_restlen = 0;
- /*
- * Break here for a read error or end-of-file.
- */
+ // Break here for a read error or end-of-file.
if (size <= 0) {
break;
}
@@ -1181,11 +1150,9 @@ retry:
char *top = ptr;
size_t to_size = (size_t)(real_size - size);
- /*
- * If there is conversion error or not enough room try using
- * another conversion. Except for when there is no
- * alternative (help files).
- */
+ // If there is conversion error or not enough room try using
+ // another conversion. Except for when there is no
+ // alternative (help files).
while ((iconv(iconv_fd, (void *)&fromp, &from_size,
&top, &to_size)
== (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
@@ -1364,7 +1331,7 @@ retry:
if (*--p < 0x80) {
u8c = *p;
} else {
- len = utf_head_off((char_u *)ptr, p);
+ len = utf_head_off(ptr, (char *)p);
p -= len;
u8c = (unsigned)utf_ptr2char((char *)p);
if (len == 0) {
@@ -1486,9 +1453,7 @@ rewind_retry:
// count the number of characters (after conversion!)
filesize += size;
- /*
- * when reading the first part of a file: guess EOL type
- */
+ // when reading the first part of a file: guess EOL type
if (fileformat == EOL_UNKNOWN) {
// First try finding a NL, for Dos and Unix
if (try_dos || try_unix) {
@@ -1553,10 +1518,8 @@ rewind_retry:
}
}
- /*
- * This loop is executed once for every character read.
- * Keep it fast!
- */
+ // This loop is executed once for every character read.
+ // Keep it fast!
if (fileformat == EOL_MAC) {
ptr--;
while (++ptr, --size >= 0) {
@@ -1658,11 +1621,9 @@ failed:
error = false;
}
- /*
- * If we get EOF in the middle of a line, note the fact and
- * complete the line ourselves.
- * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
- */
+ // If we get EOF in the middle of a line, note the fact and
+ // complete the line ourselves.
+ // In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
if (!error
&& !got_int
&& linerest != 0
@@ -1672,7 +1633,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,11 +1690,9 @@ 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.
- */
+ // In recovery mode everything but autocommands is skipped.
if (!recoverymode) {
// need to delete the last line, which comes from the empty buffer
if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY)) {
@@ -1749,7 +1708,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);
@@ -1760,20 +1719,18 @@ failed:
appended_lines_mark(from, linecnt);
}
- /*
- * If we were reading from the same terminal as where messages go,
- * the screen will have been messed up.
- * Switch on raw mode now and clear the screen.
- */
+ // If we were reading from the same terminal as where messages go,
+ // the screen will have been messed up.
+ // Switch on raw mode now and clear the screen.
if (read_stdin) {
screenclear();
}
if (got_int) {
if (!(flags & READ_DUMMY)) {
- filemess(curbuf, (char_u *)sfname, (char_u *)_(e_interr), 0);
+ filemess(curbuf, sfname, _(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 +1745,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 +1776,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,17 +1822,14 @@ 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
- /*
- * In Ex mode: cursor at last new line.
- * Otherwise: cursor at first new line.
- */
+ // In Ex mode: cursor at last new line.
+ // Otherwise: cursor at first new line.
if (exmode_active) {
curwin->w_cursor.lnum = from + linecnt;
} else {
@@ -1894,17 +1848,13 @@ failed:
}
msg_scroll = msg_save;
- /*
- * Get the marks before executing autocommands, so they can be used there.
- */
+ // Get the marks before executing autocommands, so they can be used there.
check_marks_read();
- /*
- * We remember if the last line of the read didn't have
- * an eol even when 'binary' is off, to support turning 'fixeol' off,
- * or writing the read again with 'binary' on. The latter is required
- * for ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
- */
+ // We remember if the last line of the read didn't have
+ // an eol even when 'binary' is off, to support turning 'fixeol' off,
+ // or writing the read again with 'binary' on. The latter is required
+ // for ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
curbuf->b_no_eol_lnum = read_no_eol_lnum;
// When reloading a buffer put the cursor at the first line that is
@@ -1913,9 +1863,7 @@ failed:
u_find_first_changed();
}
- /*
- * When opening a new file locate undo info and read it.
- */
+ // When opening a new file locate undo info and read it.
if (read_undo_file) {
char_u hash[UNDO_HASH_SIZE];
@@ -1933,11 +1881,9 @@ failed:
save_file_ff(curbuf);
}
- /*
- * The output from the autocommands should not overwrite anything and
- * should not be overwritten: Set msg_scroll, restore its value if no
- * output was done.
- */
+ // The output from the autocommands should not overwrite anything and
+ // should not be overwritten: Set msg_scroll, restore its value if no
+ // output was done.
msg_scroll = true;
if (filtering) {
apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
@@ -1948,7 +1894,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 +1945,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 +1964,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 +1996,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);
}
}
@@ -2062,24 +2008,24 @@ void set_forced_fenc(exarg_T *eap)
/// NULL.
/// When *pp is not set to NULL, the result is in allocated memory and "alloced"
/// is set to true.
-static char_u *next_fenc(char **pp, bool *alloced)
+static char *next_fenc(char **pp, bool *alloced)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
- char_u *p;
- char_u *r;
+ char *p;
+ char *r;
*alloced = false;
if (**pp == NUL) {
*pp = NULL;
- return (char_u *)"";
+ return "";
}
- p = (char_u *)vim_strchr((*pp), ',');
+ p = vim_strchr((*pp), ',');
if (p == NULL) {
- r = enc_canonize((char_u *)(*pp));
+ r = enc_canonize(*pp);
*pp += STRLEN(*pp);
} else {
- r = vim_strnsave((char_u *)(*pp), (size_t)(p - (char_u *)(*pp)));
- *pp = (char *)p + 1;
+ r = xstrnsave(*pp, (size_t)(p - *pp));
+ *pp = p + 1;
p = enc_canonize(r);
xfree(r);
r = p;
@@ -2103,7 +2049,7 @@ static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp)
char_u *tmpname;
char *errmsg = NULL;
- tmpname = vim_tempname();
+ tmpname = (char_u *)vim_tempname();
if (tmpname == NULL) {
errmsg = _("Can't find temp file for conversion");
} else {
@@ -2145,8 +2091,8 @@ static void check_marks_read(void)
shada_read_marks();
}
- /* Always set b_marks_read; needed when 'shada' is changed to include
- * the ' parameter after opening a buffer. */
+ // Always set b_marks_read; needed when 'shada' is changed to include
+ // the ' parameter after opening a buffer.
curbuf->b_marks_read = true;
}
@@ -2161,9 +2107,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 +2150,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 +2161,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);
@@ -2231,10 +2177,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
int wb_flags = 0;
#endif
#ifdef HAVE_ACL
- vim_acl_T acl = NULL; /* ACL copied from original file to
- backup or new file */
+ 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;
@@ -2244,16 +2190,14 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
return FAIL;
}
if (buf->b_ml.ml_mfp == NULL) {
- /* This can happen during startup when there is a stray "w" in the
- * vimrc file. */
+ // This can happen during startup when there is a stray "w" in the
+ // vimrc file.
emsg(_(e_emptybuf));
return FAIL;
}
- /*
- * Disallow writing from .exrc and .vimrc in current directory for
- * security reasons.
- */
+ // Disallow writing from .exrc and .vimrc in current directory for
+ // security reasons.
if (check_secure()) {
return FAIL;
}
@@ -2266,24 +2210,22 @@ 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
write_info.bw_iconv_fd = (iconv_t)-1;
#endif
- /* After writing a file changedtick changes but we don't want to display
- * the line. */
+ // After writing a file changedtick changes but we don't want to display
+ // the line.
ex_no_reprint = true;
- /*
- * If there is no file name yet, use the one for the written file.
- * BF_NOTEDITED is set to reflect this (in case the write fails).
- * Don't do this when the write is for a filter command.
- * Don't do this when appending.
- * Only do this when 'cpoptions' contains the 'F' flag.
- */
+ // If there is no file name yet, use the one for the written file.
+ // BF_NOTEDITED is set to reflect this (in case the write fails).
+ // Don't do this when the write is for a filter command.
+ // Don't do this when appending.
+ // Only do this when 'cpoptions' contains the 'F' flag.
if (buf->b_ffname == NULL
&& reset_changed
&& whole
@@ -2311,17 +2253,15 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
fname = sfname;
#endif
- if (buf->b_ffname != NULL && FNAMECMP(ffname, buf->b_ffname) == 0) {
+ if (buf->b_ffname != NULL && path_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.
- */
+ // Set '[ and '] marks to the lines to be written.
buf->b_op_start.lnum = start;
buf->b_op_start.col = 0;
buf->b_op_end.lnum = end;
@@ -2329,20 +2269,18 @@ 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;
- /*
- * Apply PRE autocommands.
- * Set curbuf to the buffer to be written.
- * Careful: The autocommands may call buf_write() recursively!
- */
+ // Apply PRE autocommands.
+ // Set curbuf to the buffer to be written.
+ // Careful: The autocommands may call buf_write() recursively!
if (ffname == buf->b_ffname) {
buf_ffname = true;
}
@@ -2380,9 +2318,9 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
sfname, sfname, false, curbuf, eap);
if (did_cmd) {
if (was_changed && !curbufIsChanged()) {
- /* Written everything correctly and BufWriteCmd has reset
- * 'modified': Correct the undo information so that an
- * undo now sets 'modified'. */
+ // Written everything correctly and BufWriteCmd has reset
+ // 'modified': Correct the undo information so that an
+ // undo now sets 'modified'.
u_unchanged(curbuf);
u_update_save_nr(curbuf);
}
@@ -2433,14 +2371,14 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if (nofile_err
|| aborting()) {
- /* An aborting error, interrupt or exception in the
- * autocommands. */
+ // An aborting error, interrupt or exception in the
+ // autocommands.
return FAIL;
}
if (did_cmd) {
if (buf == NULL) {
- /* The buffer was deleted. We assume it was written
- * (can't retry anyway). */
+ // The buffer was deleted. We assume it was written
+ // (can't retry anyway).
return OK;
}
if (overwriting) {
@@ -2465,12 +2403,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
return FAIL;
}
- /*
- * The autocommands may have changed the number of lines in the file.
- * When writing the whole file, adjust the end.
- * When writing part of the file, assume that the autocommands only
- * changed the number of lines that are to be written (tricky!).
- */
+ // The autocommands may have changed the number of lines in the file.
+ // When writing the whole file, adjust the end.
+ // When writing part of the file, assume that the autocommands only
+ // changed the number of lines that are to be written (tricky!).
if (buf->b_ml.ml_line_count != old_line_count) {
if (whole) { // write all
end = buf->b_ml.ml_line_count;
@@ -2487,10 +2423,8 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
}
- /*
- * The autocommands may have changed the name of the buffer, which may
- * be kept in fname, ffname and sfname.
- */
+ // The autocommands may have changed the name of the buffer, which may
+ // be kept in fname, ffname and sfname.
if (buf_ffname) {
ffname = buf->b_ffname;
}
@@ -2512,20 +2446,20 @@ 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,
#ifndef UNIX
(char_u *)sfname,
#else
- (char_u *)fname,
+ fname,
#endif
- (char_u *)"", 0); // show that we are busy
+ "", 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
@@ -2537,9 +2471,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
bufsize = BUFSIZE;
}
- /*
- * Get information about original file (if there is one).
- */
+ // Get information about original file (if there is one).
FileInfo file_info_old;
#if defined(UNIX)
perm = -1;
@@ -2556,10 +2488,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
SET_ERRMSG_NUM("E503", _("is not a file or writable device"));
goto fail;
}
- /* It's a device of some kind (or a fifo) which we can write to
- * but for which we can't make a backup. */
- device = TRUE;
- newfile = TRUE;
+ // 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;
perm = -1;
}
}
@@ -2571,8 +2503,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);
@@ -2589,10 +2521,8 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
#endif // !UNIX
if (!device && !newfile) {
- /*
- * Check if the file is really writable (when renaming the file to
- * make a backup we won't discover it later).
- */
+ // Check if the file is really writable (when renaming the file to
+ // make a backup we won't discover it later).
file_readonly = !os_file_is_writable(fname);
if (!forceit && file_readonly) {
@@ -2604,9 +2534,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
goto fail;
}
- /*
- * Check if the timestamp hasn't changed since reading the file.
- */
+ // Check if the timestamp hasn't changed since reading the file.
if (overwriting) {
retval = check_mtime(buf, &file_info_old);
if (retval == FAIL) {
@@ -2616,71 +2544,59 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
#ifdef HAVE_ACL
- /*
- * For systems that support ACL: get the ACL from the original file.
- */
+ // For systems that support ACL: get the ACL from the original file.
if (!newfile) {
acl = mch_get_acl((char_u *)fname);
}
#endif
- /*
- * If 'backupskip' is not empty, don't make a backup for some files.
- */
+ // If 'backupskip' is not empty, don't make a backup for some files.
dobackup = (p_wb || p_bk || *p_pm != NUL);
if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, (char_u *)sfname, (char_u *)ffname)) {
dobackup = false;
}
- /*
- * Save the value of got_int and reset it. We don't want a previous
- * interruption cancel writing, only hitting CTRL-C while writing should
- * abort it.
- */
+ // Save the value of got_int and reset it. We don't want a previous
+ // interruption cancel writing, only hitting CTRL-C while writing should
+ // 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;
- /*
- * If we are not appending or filtering, the file exists, and the
- * 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
- * When 'patchmode' is set also make a backup when appending.
- *
- * Do not make any backup, if 'writebackup' and 'backup' are both switched
- * off. This helps when editing large files on almost-full disks.
- */
+ // If we are not appending or filtering, the file exists, and the
+ // 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
+ // When 'patchmode' is set also make a backup when appending.
+ //
+ // Do not make any backup, if 'writebackup' and 'backup' are both switched
+ // off. This helps when editing large files on almost-full disks.
if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup) {
FileInfo file_info;
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;
- /*
- * Don't rename the file when:
- * - it's a hard link
- * - it's a symbolic link
- * - we don't have write permission in the directory
- */
+ // Don't rename the file when:
+ // - it's a hard link
+ // - it's a symbolic link
+ // - we don't have write permission in the directory
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
- * the ones from the original file.
- * First find a file name that doesn't exist yet (use some
- * arbitrary numbers).
- */
+ // Check if we can create a file and set the owner/group to
+ // the ones from the original file.
+ // First find a file name that doesn't exist yet (use some
+ // arbitrary numbers).
STRCPY(IObuff, fname);
for (i = 4913;; i += 123) {
char *tail = path_tail((char *)IObuff);
- size_t size = (size_t)((char_u *)tail - IObuff);
+ size_t size = (size_t)(tail - IObuff);
snprintf(tail, IOSIZE - size, "%d", i);
if (!os_fileinfo_link((char *)IObuff, &file_info)) {
break;
@@ -2689,7 +2605,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,20 +2613,18 @@ 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
- * can't delete an open file. */
+ // Close the file before removing it, on MS-Windows we
+ // can't delete an open file.
close(fd);
os_remove((char *)IObuff);
}
}
}
- /*
- * Break symlinks and/or hardlinks if we've been asked to.
- */
+ // Break symlinks and/or hardlinks if we've been asked to.
if ((bkc & BKC_BREAKSYMLINK) || (bkc & BKC_BREAKHARDLINK)) {
#ifdef UNIX
bool file_info_link_ok = os_fileinfo_link(fname, &file_info);
@@ -2719,7 +2633,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 +2641,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 +2650,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) {
@@ -2746,30 +2660,26 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
char *rootname;
char *p;
- /*
- * Try to make the backup in each directory in the 'bdir' option.
- *
- * Unix semantics has it, that we may have a writable file,
- * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
- * - the directory is not writable,
- * - the file may be a symbolic link,
- * - the file may belong to another user/group, etc.
- *
- * For these reasons, the existing writable file must be truncated
- * and reused. Creation of a backup COPY will be attempted.
- */
- dirp = (char *)p_bdir;
+ // Try to make the backup in each directory in the 'bdir' option.
+ //
+ // Unix semantics has it, that we may have a writable file,
+ // that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
+ // - the directory is not writable,
+ // - the file may be a symbolic link,
+ // - the file may belong to another user/group, etc.
+ //
+ // For these reasons, the existing writable file must be truncated
+ // and reused. Creation of a backup COPY will be attempted.
+ dirp = p_bdir;
while (*dirp) {
- /*
- * Isolate one directory name, using an entry in 'bdir'.
- */
+ // Isolate one directory name, using an entry in 'bdir'.
size_t dir_len = copy_option_part(&dirp, (char *)IObuff, IOSIZE, ",");
p = (char *)IObuff + dir_len;
bool trailing_pathseps = after_pathsep((char *)IObuff, p) && p[-1] == p[-2];
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) {
@@ -2787,9 +2697,9 @@ 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);
+ rootname = get_file_in_dir(fname, (char *)IObuff);
if (rootname == NULL) {
- some_error = TRUE; // out of memory
+ some_error = true; // out of memory
goto nobackup;
}
@@ -2804,13 +2714,11 @@ 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;
}
- /*
- * Check if backup file already exists.
- */
+ // Check if backup file already exists.
if (os_fileinfo(backup, &file_info_new)) {
if (os_fileinfo_id_equal(&file_info_new, &file_info_old)) {
//
@@ -2842,9 +2750,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
xfree(rootname);
- /*
- * Try to create the backup file
- */
+ // Try to create the backup file
if (backup != NULL) {
// remove old backup, if present
os_remove(backup);
@@ -2889,7 +2795,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;
@@ -2900,37 +2806,29 @@ nobackup:
char *p;
char *rootname;
- /*
- * Make a backup by renaming the original file.
- */
- /*
- * If 'cpoptions' includes the "W" flag, we don't want to
- * overwrite a read-only file. But rename may be possible
- * anyway, thus we need an extra check here.
- */
+ // Make a backup by renaming the original file.
+
+ // If 'cpoptions' includes the "W" flag, we don't want to
+ // overwrite a read-only file. But rename may be possible
+ // anyway, thus we need an extra check here.
if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
SET_ERRMSG_NUM("E504", _(err_readonly));
goto fail;
}
- /*
- *
- * Form the backup file name - change path/fo.o.h to
- * path/fo.o.h.bak Try all directories in 'backupdir', first one
- * that works is used.
- */
- dirp = (char *)p_bdir;
+ // Form the backup file name - change path/fo.o.h to
+ // path/fo.o.h.bak Try all directories in 'backupdir', first one
+ // that works is used.
+ dirp = p_bdir;
while (*dirp) {
- /*
- * Isolate one directory name and make the backup file name.
- */
+ // Isolate one directory name and make the backup file name.
size_t dir_len = copy_option_part(&dirp, (char *)IObuff, IOSIZE, ",");
p = (char *)IObuff + dir_len;
bool trailing_pathseps = after_pathsep((char *)IObuff, p) && p[-1] == p[-2];
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) {
@@ -2949,7 +2847,7 @@ nobackup:
}
if (backup == NULL) {
- rootname = (char *)get_file_in_dir((char_u *)fname, IObuff);
+ rootname = get_file_in_dir(fname, (char *)IObuff);
if (rootname == NULL) {
backup = NULL;
} else {
@@ -2959,18 +2857,16 @@ nobackup:
}
if (backup != NULL) {
- /*
- * If we are not going to keep the backup file, don't
- * delete an existing one, try to use another name.
- * Change one character, just before the extension.
- */
- if (!p_bk && os_path_exists((char_u *)backup)) {
+ // If we are not going to keep the backup file, don't
+ // delete an existing one, try to use another name.
+ // Change one character, just before the extension.
+ if (!p_bk && os_path_exists(backup)) {
p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
if (p < backup) { // empty file name ???
p = backup;
}
*p = 'z';
- while (*p > 'a' && os_path_exists((char_u *)backup)) {
+ while (*p > 'a' && os_path_exists(backup)) {
(*p)--;
}
// They all exist??? Must be something wrong!
@@ -2988,7 +2884,7 @@ nobackup:
// If the renaming of the original file to the backup file
// works, quit here.
///
- if (vim_rename((char_u *)fname, (char_u *)backup) == 0) {
+ if (vim_rename(fname, backup) == 0) {
break;
}
@@ -3049,14 +2945,14 @@ 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.
- converted = need_conversion((char_u *)fenc);
+ converted = need_conversion(fenc);
// Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
// Latin1 to Unicode conversion. This is handled in buf_write_bytes().
@@ -3089,23 +2985,26 @@ nobackup:
if (!write_info.bw_conv_buf) {
end = 0;
}
- write_info.bw_first = TRUE;
- } else
+ write_info.bw_first = true;
+ } else {
#endif
- /*
- * When the file needs to be converted with 'charconvert' after
- * writing, write to a temp file instead and let the conversion
- * overwrite the original file.
- */
+ // When the file needs to be converted with 'charconvert' after
+ // writing, write to a temp file instead and let the conversion
+ // overwrite the original file.
if (*p_ccv != NUL) {
- wfname = (char *)vim_tempname();
+ wfname = vim_tempname();
if (wfname == NULL) { // Can't write without a tempfile!
SET_ERRMSG(_("E214: Can't find temp file for writing"));
goto restore_backup;
}
}
}
+
+#ifdef HAVE_ICONV
+}
+#endif
+
if (converted && wb_flags == 0
#ifdef HAVE_ICONV
&& write_info.bw_iconv_fd == (iconv_t)-1
@@ -3115,7 +3014,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 +3036,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 ?
@@ -3200,21 +3099,21 @@ restore_backup:
// This may not work if the vim_rename() fails.
// In that case we leave the copy around.
// If file does not exist, put the copy in its place
- if (!os_path_exists((char_u *)fname)) {
- vim_rename((char_u *)backup, (char_u *)fname);
+ if (!os_path_exists(fname)) {
+ vim_rename(backup, fname);
}
// if original file does exist throw away the copy
- if (os_path_exists((char_u *)fname)) {
+ if (os_path_exists(fname)) {
os_remove(backup);
}
} else {
// try to put the original file back
- vim_rename((char_u *)backup, (char_u *)fname);
+ vim_rename(backup, fname);
}
}
// if original file no longer exists give an extra warning
- if (!newfile && !os_path_exists((char_u *)fname)) {
+ if (!newfile && !os_path_exists(fname)) {
end = 0;
}
}
@@ -3271,7 +3170,7 @@ restore_backup:
for (lnum = start; lnum <= end; lnum++) {
// The next while loop is done once for each character written.
// Keep it fast!
- ptr = (char *)ml_get_buf(buf, lnum, false) - 1;
+ ptr = ml_get_buf(buf, lnum, false) - 1;
if (write_undo_file) {
sha256_update(&sha_ctx, (char_u *)ptr + 1, (uint32_t)(STRLEN(ptr + 1) + 1));
}
@@ -3366,7 +3265,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.
@@ -3476,7 +3375,7 @@ restore_backup:
end = 1; // success
}
} else {
- if (vim_rename((char_u *)backup, (char_u *)fname) == 0) {
+ if (vim_rename(backup, fname) == 0) {
end = 1;
}
}
@@ -3485,7 +3384,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 +3394,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)) {
@@ -3534,8 +3433,8 @@ restore_backup:
set_keep_msg(msg_trunc_attr((char *)IObuff, false, 0), 0);
}
- /* When written everything correctly: reset 'modified'. Unless not
- * writing to the original file and '+' is not in 'cpoptions'. */
+ // When written everything correctly: reset 'modified'. Unless not
+ // writing to the original file and '+' is not in 'cpoptions'.
if (reset_changed && whole && !append
&& !write_info.bw_conv_error
&& (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)) {
@@ -3550,10 +3449,8 @@ restore_backup:
u_update_save_nr(buf);
}
- /*
- * If written to the current file, update the timestamp of the swap file
- * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
- */
+ // If written to the current file, update the timestamp of the swap file
+ // and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
if (overwriting) {
ml_timestamp(buf);
if (append) {
@@ -3563,22 +3460,18 @@ restore_backup:
}
}
- /*
- * If we kept a backup until now, and we are in patch mode, then we make
- * the backup file our 'original' file.
- */
+ // If we kept a backup until now, and we are in patch mode, then we make
+ // 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) {
- /*
- * If the original file does not exist yet
- * the current backup file becomes the original file
- */
+ // If the original file does not exist yet
+ // the current backup file becomes the original file
if (org == NULL) {
emsg(_("E205: Patchmode: can't save original file"));
- } else if (!os_path_exists((char_u *)org)) {
- vim_rename((char_u *)backup, (char_u *)org);
+ } else if (!os_path_exists(org)) {
+ vim_rename(backup, org);
XFREE_CLEAR(backup); // don't delete the file
#ifdef UNIX
os_file_settime(org,
@@ -3586,12 +3479,9 @@ restore_backup:
(double)file_info_old.stat.st_mtim.tv_sec);
#endif
}
- }
- /*
- * If there is no backup file, remember that a (new) file was
- * created.
- */
- else {
+ } else {
+ // If there is no backup file, remember that a (new) file was
+ // created.
int empty_fd;
if (org == NULL
@@ -3609,9 +3499,7 @@ restore_backup:
}
}
- /*
- * Remove the backup unless 'backup' option is set
- */
+ // Remove the backup unless 'backup' option is set
if (!p_bk && backup != NULL
&& !write_info.bw_conv_error
&& os_remove(backup) != 0) {
@@ -3620,11 +3508,9 @@ restore_backup:
goto nofail;
- /*
- * Finish up. We get here either after failure or success.
- */
+ // 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
@@ -3687,10 +3573,8 @@ nofail:
}
msg_scroll = msg_save;
- /*
- * When writing the whole file and 'undofile' is set, also write the undo
- * file.
- */
+ // When writing the whole file and 'undofile' is set, also write the undo
+ // file.
if (retval == OK && write_undo_file) {
char hash[UNDO_HASH_SIZE];
@@ -3703,31 +3587,29 @@ nofail:
curbuf->b_no_eol_lnum = 0; // in case it was set by the previous read
- /*
- * Apply POST autocommands.
- * Careful: The autocommands may call buf_write() recursively!
- */
+ // Apply POST autocommands.
+ // Careful: The autocommands may call buf_write() recursively!
aucmd_prepbuf(&aco, buf);
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;
}
}
@@ -3834,20 +3716,20 @@ void msg_add_lines(int insert_space, long lnum, off_T nchars)
{
char_u *p;
- p = IObuff + STRLEN(IObuff);
+ p = (char_u *)IObuff + STRLEN(IObuff);
if (insert_space) {
*p++ = ' ';
}
if (shortmess(SHM_LINES)) {
- vim_snprintf((char *)p, (size_t)(IOSIZE - (p - IObuff)), "%" PRId64 "L, %" PRId64 "B",
+ vim_snprintf((char *)p, (size_t)(IOSIZE - (p - (char_u *)IObuff)), "%" PRId64 "L, %" PRId64 "B",
(int64_t)lnum, (int64_t)nchars);
} else {
- vim_snprintf((char *)p, (size_t)(IOSIZE - (p - IObuff)),
+ vim_snprintf((char *)p, (size_t)(IOSIZE - (p - (char_u *)IObuff)),
NGETTEXT("%" PRId64 " line, ", "%" PRId64 " lines, ", lnum),
(int64_t)lnum);
p += STRLEN(p);
- vim_snprintf((char *)p, (size_t)(IOSIZE - (p - IObuff)),
+ vim_snprintf((char *)p, (size_t)(IOSIZE - (p - (char_u *)IObuff)),
NGETTEXT("%" PRId64 " byte", "%" PRId64 " bytes", nchars),
(int64_t)nchars);
}
@@ -3907,18 +3789,14 @@ static int buf_write_bytes(struct bw_info *ip)
int flags = ip->bw_flags; // extra flags
#endif
- /*
- * Skip conversion when writing the BOM.
- */
+ // Skip conversion when writing the BOM.
if (!(flags & FIO_NOCONVERT)) {
char_u *p;
unsigned c;
int n;
if (flags & FIO_UTF8) {
- /*
- * Convert latin1 in the buffer to UTF-8 in the file.
- */
+ // Convert latin1 in the buffer to UTF-8 in the file.
p = ip->bw_conv_buf; // translate to buffer
for (wlen = 0; wlen < len; wlen++) {
p += utf_char2bytes(buf[wlen], (char *)p);
@@ -3926,10 +3804,8 @@ static int buf_write_bytes(struct bw_info *ip)
buf = ip->bw_conv_buf;
len = (int)(p - ip->bw_conv_buf);
} else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1)) {
- /*
- * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
- * Latin1 chars in the file.
- */
+ // Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
+ // Latin1 chars in the file.
if (flags & FIO_LATIN1) {
p = buf; // translate in-place (can only get shorter)
} else {
@@ -3939,9 +3815,9 @@ static int buf_write_bytes(struct bw_info *ip)
if (wlen == 0 && ip->bw_restlen != 0) {
int l;
- /* Use remainder of previous call. Append the start of
- * buf[] to get a full sequence. Might still be too
- * short! */
+ // Use remainder of previous call. Append the start of
+ // buf[] to get a full sequence. Might still be too
+ // short!
l = CONV_RESTLEN - ip->bw_restlen;
if (l > len) {
l = len;
@@ -3949,9 +3825,9 @@ static int buf_write_bytes(struct bw_info *ip)
memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
if (n > ip->bw_restlen + len) {
- /* We have an incomplete byte sequence at the end to
- * be written. We can't convert it without the
- * remaining bytes. Keep them for the next call. */
+ // We have an incomplete byte sequence at the end to
+ // be written. We can't convert it without the
+ // remaining bytes. Keep them for the next call.
if (ip->bw_restlen + len > CONV_RESTLEN) {
return FAIL;
}
@@ -3975,9 +3851,9 @@ static int buf_write_bytes(struct bw_info *ip)
} else {
n = utf_ptr2len_len(buf + wlen, len - wlen);
if (n > len - wlen) {
- /* We have an incomplete byte sequence at the end to
- * be written. We can't convert it without the
- * remaining bytes. Keep them for the next call. */
+ // We have an incomplete byte sequence at the end to
+ // be written. We can't convert it without the
+ // remaining bytes. Keep them for the next call.
if (len - wlen > CONV_RESTLEN) {
return FAIL;
}
@@ -3994,11 +3870,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) {
@@ -4020,9 +3896,9 @@ static int buf_write_bytes(struct bw_info *ip)
if (ip->bw_restlen > 0) {
char *fp;
- /* Need to concatenate the remainder of the previous call and
- * the bytes of the current call. Use the end of the
- * conversion buffer for this. */
+ // Need to concatenate the remainder of the previous call and
+ // the bytes of the current call. Use the end of the
+ // conversion buffer for this.
fromlen = (size_t)len + (size_t)ip->bw_restlen;
fp = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
@@ -4042,23 +3918,20 @@ static int buf_write_bytes(struct bw_info *ip)
// output the initial shift state sequence
(void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
- /* There is a bug in iconv() on Linux (which appears to be
- * wide-spread) which sets "to" to NULL and messes up "tolen".
- */
+ // There is a bug in iconv() on Linux (which appears to be
+ // wide-spread) which sets "to" to NULL and messes up "tolen".
if (to == NULL) {
to = (char *)ip->bw_conv_buf;
tolen = save_len;
}
- ip->bw_first = FALSE;
+ ip->bw_first = false;
}
- /*
- * If iconv() has an error or there is not enough room, fail.
- */
+ // If iconv() has an error or there is not enough room, fail.
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;
}
@@ -4110,8 +3983,8 @@ static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
} else if (flags & (FIO_UCS2 | FIO_UTF16)) {
if (c >= 0x10000) {
if (flags & FIO_UTF16) {
- /* Make two words, ten bits of the character in each. First
- * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
+ // Make two words, ten bits of the character in each. First
+ // word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff
c -= 0x10000;
if (c >= 0x100000) {
error = true;
@@ -4155,21 +4028,21 @@ static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
/// @param fenc file encoding to check
///
/// @return true if conversion is required
-static bool need_conversion(const char_u *fenc)
+static bool need_conversion(const char *fenc)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int same_encoding;
int enc_flags;
int fenc_flags;
- if (*fenc == NUL || STRCMP(p_enc, fenc) == 0) {
- same_encoding = TRUE;
+ if (*fenc == NUL || strcmp(p_enc, fenc) == 0) {
+ 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);
- fenc_flags = get_fio_flags(fenc);
+ enc_flags = get_fio_flags((char_u *)p_enc);
+ fenc_flags = get_fio_flags((char_u *)fenc);
same_encoding = (enc_flags != 0 && fenc_flags == enc_flags);
}
if (same_encoding) {
@@ -4192,7 +4065,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 +4169,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.
@@ -4316,7 +4189,7 @@ void shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
if (buf->b_sfname != buf->b_ffname) {
XFREE_CLEAR(buf->b_sfname);
}
- p = (char *)path_shorten_fname((char_u *)buf->b_ffname, dirname);
+ p = path_shorten_fname(buf->b_ffname, (char *)dirname);
if (p != NULL) {
buf->b_sfname = xstrdup(p);
buf->b_fname = buf->b_sfname;
@@ -4386,7 +4259,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);
@@ -4608,7 +4481,7 @@ int put_time(FILE *fd, time_t time_)
/// function will (attempts to?) copy the file across if rename fails -- webb
///
/// @return -1 for failure, 0 for success
-int vim_rename(const char_u *from, const char_u *to)
+int vim_rename(const char *from, const char *to)
FUNC_ATTR_NONNULL_ALL
{
int fd_in;
@@ -4622,13 +4495,11 @@ int vim_rename(const char_u *from, const char_u *to)
#endif
bool use_tmp_file = false;
- /*
- * When the names are identical, there is nothing to do. When they refer
- * to the same file (ignoring case and slash/backslash differences) but
- * the file name differs we need to go through a temp file.
- */
- if (FNAMECMP(from, to) == 0) {
- if (p_fic && (STRCMP(path_tail((char *)from), path_tail((char *)to))
+ // When the names are identical, there is nothing to do. When they refer
+ // to the same file (ignoring case and slash/backslash differences) but
+ // the file name differs we need to go through a temp file.
+ if (path_fnamecmp(from, to) == 0) {
+ if (p_fic && (strcmp(path_tail((char *)from), path_tail((char *)to))
!= 0)) {
use_tmp_file = true;
} else {
@@ -4654,10 +4525,8 @@ int vim_rename(const char_u *from, const char_u *to)
if (use_tmp_file) {
char_u tempname[MAXPATHL + 1];
- /*
- * Find a name that doesn't exist and is in the same directory.
- * Rename "from" to "tempname" and then rename "tempname" to "to".
- */
+ // Find a name that doesn't exist and is in the same directory.
+ // Rename "from" to "tempname" and then rename "tempname" to "to".
if (STRLEN(from) >= MAXPATHL - 5) {
return -1;
}
@@ -4666,14 +4535,14 @@ int vim_rename(const char_u *from, const char_u *to)
char *tail = path_tail((char *)tempname);
snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - (char *)tempname - 1)), "%d", n);
- if (!os_path_exists(tempname)) {
- if (os_rename(from, tempname) == OK) {
- if (os_rename(tempname, to) == OK) {
+ if (!os_path_exists((char *)tempname)) {
+ if (os_rename((char_u *)from, tempname) == OK) {
+ if (os_rename(tempname, (char_u *)to) == OK) {
return 0;
}
// Strange, the second step failed. Try moving the
// file back and return failure.
- (void)os_rename(tempname, from);
+ (void)os_rename(tempname, (char_u *)from);
return -1;
}
// If it fails for one temp name it will most likely fail
@@ -4684,28 +4553,22 @@ int vim_rename(const char_u *from, const char_u *to)
return -1;
}
- /*
- * Delete the "to" file, this is required on some systems to make the
- * os_rename() work, on other systems it makes sure that we don't have
- * two files when the os_rename() fails.
- */
+ // Delete the "to" file, this is required on some systems to make the
+ // os_rename() work, on other systems it makes sure that we don't have
+ // two files when the os_rename() fails.
os_remove((char *)to);
- /*
- * First try a normal rename, return if it works.
- */
- if (os_rename(from, to) == OK) {
+ // First try a normal rename, return if it works.
+ if (os_rename((char_u *)from, (char_u *)to) == OK) {
return 0;
}
- /*
- * Rename() failed, try copying the file.
- */
- perm = os_getperm((const char *)from);
+ // Rename() failed, try copying the file.
+ perm = os_getperm(from);
#ifdef HAVE_ACL
// For systems that support ACL: get the ACL from the original file.
- acl = mch_get_acl(from);
+ acl = mch_get_acl((char_u *)from);
#endif
fd_in = os_open((char *)from, O_RDONLY, 0);
if (fd_in < 0) {
@@ -4758,7 +4621,7 @@ int vim_rename(const char_u *from, const char_u *to)
os_setperm((const char *)to, perm);
#endif
#ifdef HAVE_ACL
- mch_set_acl(to, acl);
+ mch_set_acl((char_u *)to, acl);
mch_free_acl(acl);
#endif
if (errmsg != NULL) {
@@ -4769,7 +4632,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 +4641,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 +4649,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()
@@ -4841,13 +4704,13 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf)
buf_T *tbuf = curbuf;
int retval = OK;
linenr_T lnum;
- char_u *p;
+ char *p;
// Copy the lines in "frombuf" to "tobuf".
curbuf = tobuf;
for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; lnum++) {
- p = vim_strsave(ml_get_buf(frombuf, lnum, false));
- if (ml_append(lnum - 1, (char *)p, 0, false) == FAIL) {
+ p = xstrdup(ml_get_buf(frombuf, lnum, false));
+ if (ml_append(lnum - 1, p, 0, false) == FAIL) {
xfree(p);
retval = FAIL;
break;
@@ -4882,7 +4745,7 @@ int buf_check_timestamp(buf_T *buf)
FUNC_ATTR_NONNULL_ALL
{
int retval = 0;
- char_u *path;
+ char *path;
char *mesg = NULL;
char *mesg2 = "";
bool helpmesg = false;
@@ -4897,7 +4760,7 @@ int buf_check_timestamp(buf_T *buf)
uint64_t orig_size = buf->b_orig_size;
int orig_mode = buf->b_orig_mode;
static bool busy = false;
- char_u *s;
+ char *s;
char *reason;
bufref_T bufref;
@@ -4937,7 +4800,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) {
@@ -4972,12 +4835,12 @@ int buf_check_timestamp(buf_T *buf)
if (!bufref_valid(&bufref)) {
emsg(_("E246: FileChangedShell autocommand deleted buffer"));
}
- s = (char_u *)get_vim_var_str(VV_FCS_CHOICE);
- if (STRCMP(s, "reload") == 0 && *reason != 'd') {
+ s = get_vim_var_str(VV_FCS_CHOICE);
+ if (strcmp(s, "reload") == 0 && *reason != 'd') {
reload = RELOAD_NORMAL;
- } else if (STRCMP(s, "edit") == 0) {
+ } else if (strcmp(s, "edit") == 0) {
reload = RELOAD_DETECT;
- } else if (STRCMP(s, "ask") == 0) {
+ } else if (strcmp(s, "ask") == 0) {
n = false;
} else {
return 2;
@@ -5017,7 +4880,7 @@ int buf_check_timestamp(buf_T *buf)
}
}
} else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
- && os_path_exists((char_u *)buf->b_ffname)) {
+ && os_path_exists(buf->b_ffname)) {
retval = 1;
mesg = _("W13: Warning: File \"%s\" has been created after editing started");
buf->b_flags |= BF_NEW_W;
@@ -5025,7 +4888,7 @@ int buf_check_timestamp(buf_T *buf)
}
if (mesg != NULL) {
- path = (char_u *)home_replace_save(buf, buf->b_fname);
+ path = home_replace_save(buf, buf->b_fname);
if (!helpmesg) {
mesg2 = "";
}
@@ -5040,8 +4903,8 @@ int buf_check_timestamp(buf_T *buf)
xstrlcat(tbuf, "\n", tbuf_len - 1);
xstrlcat(tbuf, mesg2, tbuf_len - 1);
}
- switch (do_dialog(VIM_WARNING, (char_u *)_("Warning"), (char_u *)tbuf,
- (char_u *)_("&OK\n&Load File\nLoad File &and Options"),
+ switch (do_dialog(VIM_WARNING, _("Warning"), tbuf,
+ _("&OK\n&Load File\nLoad File &and Options"),
1, NULL, true)) {
case 2:
reload = RELOAD_NORMAL;
@@ -5075,7 +4938,7 @@ int buf_check_timestamp(buf_T *buf)
redraw_cmdline = false;
}
}
- already_warned = TRUE;
+ already_warned = true;
}
xfree(path);
@@ -5306,8 +5169,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 +5180,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);
@@ -5495,7 +5358,7 @@ static bool vim_settempdir(char *tempdir)
///
/// @return pointer to the temp file name or NULL if Nvim can't create
/// temporary directory for its own temporary files.
-char_u *vim_tempname(void)
+char *vim_tempname(void)
{
// Temp filename counter.
static uint64_t temp_count;
@@ -5507,10 +5370,10 @@ char_u *vim_tempname(void)
// There is no need to check if the file exists, because we own the directory
// and nobody else creates a file in it.
- char_u template[TEMP_FILE_PATH_MAXLEN];
- snprintf((char *)template, TEMP_FILE_PATH_MAXLEN,
+ char template[TEMP_FILE_PATH_MAXLEN];
+ snprintf(template, TEMP_FILE_PATH_MAXLEN,
"%s%" PRIu64, tempdir, temp_count++);
- return vim_strsave(template);
+ return xstrdup(template);
}
/// Tries matching a filename with a "pattern" ("prog" is NULL), or use the
@@ -5542,12 +5405,10 @@ bool match_file_pat(char *pattern, regprog_T **prog, char *fname, char *sfname,
}
}
- /*
- * Try for a match with the pattern with:
- * 1. the full file name, when the pattern has a '/'.
- * 2. the short file name, when the pattern has a '/'.
- * 3. the tail of the file name, when the pattern has no '/'.
- */
+ // Try for a match with the pattern with:
+ // 1. the full file name, when the pattern has a '/'.
+ // 2. the short file name, when the pattern has a '/'.
+ // 3. the tail of the file name, when the pattern has no '/'.
if (regmatch.regprog != NULL
&& ((allow_dirs
&& (vim_regexec(&regmatch, fname, (colnr_T)0)
@@ -5606,8 +5467,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 +5486,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 +5572,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 +5606,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 +5619,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..2e8d282ede 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -111,7 +111,7 @@ static int prev_lnum_lvl = -1;
#define DONE_FOLD 2 // did find a fold
static size_t foldstartmarkerlen;
-static char_u *foldendmarker;
+static char *foldendmarker;
static size_t foldendmarkerlen;
// Exported folding functions. {{{1
@@ -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
@@ -982,7 +982,7 @@ void foldAdjustVisual(void)
}
pos_T *start, *end;
- char_u *ptr;
+ char *ptr;
if (ltoreq(VIsual, curwin->w_cursor)) {
start = &VIsual;
@@ -1573,16 +1573,16 @@ static void foldCreateMarkers(win_T *wp, pos_T start, pos_T end)
// foldAddMarker() {{{2
/// Add "marker[markerlen]" in 'commentstring' to position `pos`.
-static void foldAddMarker(buf_T *buf, pos_T pos, const char_u *marker, size_t markerlen)
+static void foldAddMarker(buf_T *buf, pos_T pos, const char *marker, size_t markerlen)
{
- char_u *cms = buf->b_p_cms;
- char_u *newline;
- char_u *p = (char_u *)strstr((char *)buf->b_p_cms, "%s");
+ char *cms = buf->b_p_cms;
+ char *newline;
+ char *p = strstr(buf->b_p_cms, "%s");
bool line_is_comment = false;
linenr_T lnum = pos.lnum;
// Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end
- char_u *line = ml_get_buf(buf, lnum, false);
+ char *line = ml_get_buf(buf, lnum, false);
size_t line_len = STRLEN(line);
size_t added = 0;
@@ -1632,16 +1632,16 @@ static void deleteFoldMarkers(win_T *wp, fold_T *fp, int recursive, linenr_T lnu
/// Delete 'commentstring' if it matches.
/// If the marker is not found, there is no error message. Could be a missing
/// close-marker.
-static void foldDelMarker(buf_T *buf, linenr_T lnum, char_u *marker, size_t markerlen)
+static void foldDelMarker(buf_T *buf, linenr_T lnum, char *marker, size_t markerlen)
{
// end marker may be missing and fold extends below the last line
if (lnum > buf->b_ml.ml_line_count) {
return;
}
- char_u *cms = buf->b_p_cms;
- char_u *line = ml_get_buf(buf, lnum, false);
- for (char_u *p = line; *p != NUL; p++) {
+ char *cms = buf->b_p_cms;
+ char *line = ml_get_buf(buf, lnum, false);
+ for (char *p = line; *p != NUL; p++) {
if (STRNCMP(p, marker, markerlen) != 0) {
continue;
}
@@ -1652,7 +1652,7 @@ static void foldDelMarker(buf_T *buf, linenr_T lnum, char_u *marker, size_t mark
}
if (*cms != NUL) {
// Also delete 'commentstring' if it matches.
- char_u *cms2 = (char_u *)strstr((char *)cms, "%s");
+ char *cms2 = strstr(cms, "%s");
if (p - line >= cms2 - cms
&& STRNCMP(p - (cms2 - cms), cms, cms2 - cms) == 0
&& STRNCMP(p + len, cms2 + 2, STRLEN(cms2 + 2)) == 0) {
@@ -1662,7 +1662,7 @@ static void foldDelMarker(buf_T *buf, linenr_T lnum, char_u *marker, size_t mark
}
if (u_save(lnum - 1, lnum + 1) == OK) {
// Make new line: text-before-marker + text-after-marker
- char_u *newline = xmalloc(STRLEN(line) - len + 1);
+ char *newline = xmalloc(STRLEN(line) - len + 1);
assert(p >= line);
memcpy(newline, line, (size_t)(p - line));
STRCPY(newline + (p - line), p + len);
@@ -1683,10 +1683,10 @@ static void foldDelMarker(buf_T *buf, linenr_T lnum, char_u *marker, size_t mark
/// @return the text for a closed fold
///
/// Otherwise the result is in allocated memory.
-char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo, char_u *buf)
+char *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldinfo, char *buf)
FUNC_ATTR_NONNULL_ARG(1)
{
- char_u *text = NULL;
+ char *text = NULL;
// an error occurred when evaluating 'fdt' setting
static bool got_fdt_error = false;
int save_did_emsg = did_emsg;
@@ -1728,9 +1728,7 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldin
curbuf = wp->w_buffer;
emsg_silent++; // handle exceptions, but don't display errors
- text =
- (char_u *)eval_to_string_safe((char *)wp->w_p_fdt, NULL,
- was_set_insecurely(wp, "foldtext", OPT_LOCAL));
+ text = eval_to_string_safe(wp->w_p_fdt, NULL, was_set_insecurely(wp, "foldtext", OPT_LOCAL));
emsg_silent--;
if (text == NULL || did_emsg) {
@@ -1751,23 +1749,23 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldin
if (text != NULL) {
// Replace unprintable characters, if there are any. But
// replace a TAB with a space.
- char_u *p;
+ char *p;
for (p = text; *p != NUL; p++) {
- int len = utfc_ptr2len((char *)p);
+ int len = utfc_ptr2len(p);
if (len > 1) {
- if (!vim_isprintc(utf_ptr2char((char *)p))) {
+ if (!vim_isprintc(utf_ptr2char(p))) {
break;
}
p += len - 1;
} else if (*p == TAB) {
*p = ' ';
- } else if (ptr2cells((char *)p) > 1) {
+ } else if (ptr2cells(p) > 1) {
break;
}
}
if (*p != NUL) {
- p = (char_u *)transstr((const char *)text, true);
+ p = transstr((const char *)text, true);
xfree(text);
text = p;
}
@@ -1776,7 +1774,7 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldin
if (text == NULL) {
unsigned long count = (unsigned long)(lnume - lnum + 1);
- vim_snprintf((char *)buf, FOLD_TEXT_LEN,
+ vim_snprintf(buf, FOLD_TEXT_LEN,
NGETTEXT("+--%3ld line folded",
"+--%3ld lines folded ", count),
count);
@@ -1787,17 +1785,17 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldin
// foldtext_cleanup() {{{2
/// Remove 'foldmarker' and 'commentstring' from "str" (in-place).
-static void foldtext_cleanup(char_u *str)
+static void foldtext_cleanup(char *str)
{
// Ignore leading and trailing white space in 'commentstring'.
- char_u *cms_start = (char_u *)skipwhite((char *)curbuf->b_p_cms);
+ char *cms_start = 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--;
}
// locate "%s" in 'commentstring', use the part before and after it.
- char_u *cms_end = (char_u *)strstr((char *)cms_start, "%s");
+ char *cms_end = strstr(cms_start, "%s");
size_t cms_elen = 0;
if (cms_end != NULL) {
cms_elen = cms_slen - (size_t)(cms_end - cms_start);
@@ -1809,7 +1807,7 @@ static void foldtext_cleanup(char_u *str)
}
// skip "%s" and white space after it
- char_u *s = (char_u *)skipwhite((char *)cms_end + 2);
+ char *s = skipwhite(cms_end + 2);
cms_elen -= (size_t)(s - cms_end);
cms_end = s;
}
@@ -1818,7 +1816,7 @@ static void foldtext_cleanup(char_u *str)
bool did1 = false;
bool did2 = false;
- for (char_u *s = str; *s != NUL;) {
+ for (char *s = str; *s != NUL;) {
size_t len = 0;
if (STRNCMP(s, curwin->w_p_fmr, foldstartmarkerlen) == 0) {
len = foldstartmarkerlen;
@@ -1832,7 +1830,7 @@ static void foldtext_cleanup(char_u *str)
// May remove 'commentstring' start. Useful when it's a double
// quote and we already removed a double quote.
- char_u *p;
+ char *p;
for (p = s; p > str && ascii_iswhite(p[-1]); p--) {}
if (p >= str + cms_slen
&& STRNCMP(p - cms_slen, cms_start, cms_slen) == 0) {
@@ -2850,11 +2848,11 @@ static void foldlevelIndent(fline_T *flp)
linenr_T lnum = flp->lnum + flp->off;
buf_T *buf = flp->wp->w_buffer;
- char_u *s = (char_u *)skipwhite((char *)ml_get_buf(buf, lnum, false));
+ char *s = skipwhite(ml_get_buf(buf, lnum, false));
// 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 +2905,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,7 +2983,7 @@ 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, ',');
+ foldendmarker = vim_strchr(wp->w_p_fmr, ',');
foldstartmarkerlen = (size_t)(foldendmarker++ - wp->w_p_fmr);
foldendmarkerlen = STRLEN(foldendmarker);
}
@@ -3003,23 +3001,23 @@ 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;
- int cstart = *startmarker;
+ char *startmarker = flp->wp->w_p_fmr;
+ int cstart = (unsigned char)(*startmarker);
startmarker++;
- int cend = *foldendmarker;
+ int cend = (unsigned char)(*foldendmarker);
// Default: no start found, next level is same as current level
flp->start = 0;
flp->lvl_next = flp->lvl;
- char_u *s = ml_get_buf(flp->wp->w_buffer, flp->lnum + flp->off, false);
+ char *s = ml_get_buf(flp->wp->w_buffer, flp->lnum + flp->off, false);
while (*s) {
if (*s == cstart
&& STRNCMP(s + 1, startmarker, foldstartmarkerlen - 1) == 0) {
// found startmarker: set flp->lvl
s += foldstartmarkerlen;
if (ascii_isdigit(*s)) {
- int n = atoi((char *)s);
+ int n = atoi(s);
if (n > 0) {
flp->lvl = n;
flp->lvl_next = n;
@@ -3039,7 +3037,7 @@ static void foldlevelMarker(fline_T *flp)
// found endmarker: set flp->lvl_next
s += foldendmarkerlen;
if (ascii_isdigit(*s)) {
- int n = atoi((char *)s);
+ int n = atoi(s);
if (n > 0) {
flp->lvl = n;
flp->lvl_next = n - 1;
@@ -3212,19 +3210,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,14 +3231,14 @@ 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;
linenr_T foldstart = (linenr_T)get_vim_var_nr(VV_FOLDSTART);
linenr_T foldend = (linenr_T)get_vim_var_nr(VV_FOLDEND);
- char_u *dashes = (char_u *)get_vim_var_str(VV_FOLDDASHES);
+ char *dashes = get_vim_var_str(VV_FOLDDASHES);
if (foldstart > 0 && foldend <= curbuf->b_ml.ml_line_count) {
// Find first non-empty line in the fold.
linenr_T lnum;
@@ -3251,12 +3249,12 @@ void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
// Find interesting text in this line.
- char_u *s = (char_u *)skipwhite((char *)ml_get(lnum));
+ char_u *s = (char_u *)skipwhite(ml_get(lnum));
// skip C comment-start
if (s[0] == '/' && (s[1] == '*' || s[1] == '/')) {
s = (char_u *)skipwhite((char *)s + 2);
if (*skipwhite((char *)s) == NUL && lnum + 1 < foldend) {
- s = (char_u *)skipwhite((char *)ml_get(lnum + 1));
+ s = (char_u *)skipwhite(ml_get(lnum + 1));
if (*s == '*') {
s = (char_u *)skipwhite((char *)s + 1);
}
@@ -3268,20 +3266,20 @@ void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+ STRLEN(dashes) // for %s
+ 20 // for %3ld
+ STRLEN(s); // concatenated
- char_u *r = xmalloc(len);
- snprintf((char *)r, len, txt, dashes, count);
+ char *r = xmalloc(len);
+ snprintf(r, len, txt, dashes, count);
len = STRLEN(r);
STRCAT(r, s);
// remove 'foldmarker' and 'commentstring'
foldtext_cleanup(r + len);
- rettv->vval.v_string = (char *)r;
+ rettv->vval.v_string = r;
}
}
/// "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];
+ char buf[FOLD_TEXT_LEN];
static bool entered = false;
rettv->v_type = VAR_STRING;
@@ -3298,11 +3296,11 @@ void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr)
foldinfo_T info = fold_info(curwin, lnum);
if (info.fi_lines > 0) {
- char_u *text = get_foldtext(curwin, lnum, lnum + info.fi_lines - 1, info, buf);
+ char *text = get_foldtext(curwin, lnum, lnum + info.fi_lines - 1, info, buf);
if (text == buf) {
- text = vim_strsave(text);
+ text = xstrdup(text);
}
- rettv->vval.v_string = (char *)text;
+ rettv->vval.v_string = text;
}
entered = false;
diff --git a/src/nvim/fold.h b/src/nvim/fold.h
index f34e6d43c3..395cd8e30a 100644
--- a/src/nvim/fold.h
+++ b/src/nvim/fold.h
@@ -8,10 +8,8 @@
#include "nvim/pos.h"
#include "nvim/types.h"
-/*
- * Info used to pass info about a fold from the fold-detection code to the
- * code that displays the foldcolumn.
- */
+// Info used to pass info about a fold from the fold-detection code to the
+// code that displays the foldcolumn.
typedef struct foldinfo {
linenr_T fi_lnum; // line number where fold starts
int fi_level; // level of the fold; when this is zero the
diff --git a/src/nvim/garray.c b/src/nvim/garray.c
index 7a3c14b1bb..adc3eda5ca 100644
--- a/src/nvim/garray.c
+++ b/src/nvim/garray.c
@@ -123,7 +123,7 @@ void ga_remove_duplicate_strings(garray_T *gap)
// loop over the growing array in reverse
for (int i = gap->ga_len - 1; i > 0; i--) {
- if (FNAMECMP(fnames[i - 1], fnames[i]) == 0) {
+ if (path_fnamecmp(fnames[i - 1], fnames[i]) == 0) {
xfree(fnames[i]);
// close the gap (move all strings one slot lower)
@@ -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..ea66be7ee8 100755
--- a/src/nvim/generators/gen_api_ui_events.lua
+++ b/src/nvim/generators/gen_api_ui_events.lua
@@ -75,6 +75,8 @@ local function call_ui_event_method(output, ev)
hlattrs_args_count = hlattrs_args_count + 1
elseif kind == 'Object' then
output:write('args.items['..(j-1)..'];\n')
+ elseif kind == 'Window' then
+ output:write('(Window)args.items['..(j-1)..'].data.integer;\n')
else
output:write('args.items['..(j-1)..'].data.'..string.lower(kind)..';\n')
end
@@ -125,7 +127,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 +136,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 +146,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/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index 0454c54faf..24b4739fc7 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -115,7 +115,7 @@ local value_dumpers = {
}
local get_value = function(v)
- return '(char_u *) ' .. value_dumpers[type(v)](v)
+ return '(char *) ' .. value_dumpers[type(v)](v)
end
local get_defaults = function(d,n)
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 0f55158733..0f0e3aece1 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -81,33 +81,29 @@ 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
-/*
- * Variables used by vgetorpeek() and flush_buffers()
- *
- * typebuf.tb_buf[] contains all characters that are not consumed yet.
- * typebuf.tb_buf[typebuf.tb_off] is the first valid character.
- * typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len - 1] is the last valid char.
- * typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len] must be NUL.
- * The head of the buffer may contain the result of mappings, abbreviations
- * and @a commands. The length of this part is typebuf.tb_maplen.
- * typebuf.tb_silent is the part where <silent> applies.
- * After the head are characters that come from the terminal.
- * typebuf.tb_no_abbr_cnt is the number of characters in typebuf.tb_buf that
- * should not be considered for abbreviations.
- * Some parts of typebuf.tb_buf may not be mapped. These parts are remembered
- * in typebuf.tb_noremap[], which is the same length as typebuf.tb_buf and
- * contains RM_NONE for the characters that are not to be remapped.
- * typebuf.tb_noremap[typebuf.tb_off] is the first valid flag.
- * (typebuf has been put in globals.h, because check_termcode() needs it).
- */
+// Variables used by vgetorpeek() and flush_buffers()
+//
+// typebuf.tb_buf[] contains all characters that are not consumed yet.
+// typebuf.tb_buf[typebuf.tb_off] is the first valid character.
+// typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len - 1] is the last valid char.
+// typebuf.tb_buf[typebuf.tb_off + typebuf.tb_len] must be NUL.
+// The head of the buffer may contain the result of mappings, abbreviations
+// and @a commands. The length of this part is typebuf.tb_maplen.
+// typebuf.tb_silent is the part where <silent> applies.
+// After the head are characters that come from the terminal.
+// typebuf.tb_no_abbr_cnt is the number of characters in typebuf.tb_buf that
+// should not be considered for abbreviations.
+// Some parts of typebuf.tb_buf may not be mapped. These parts are remembered
+// in typebuf.tb_noremap[], which is the same length as typebuf.tb_buf and
+// contains RM_NONE for the characters that are not to be remapped.
+// typebuf.tb_noremap[typebuf.tb_off] is the first valid flag.
+// (typebuf has been put in globals.h, because check_termcode() needs it).
#define RM_YES 0 // tb_noremap: remap
#define RM_NONE 1 // tb_noremap: don't remap
#define RM_SCRIPT 2 // tb_noremap: remap local script mappings
@@ -126,9 +122,7 @@ static size_t last_recorded_len = 0; // number of last recorded chars
# include "getchar.c.generated.h"
#endif
-/*
- * Free and clear a buffer.
- */
+// Free and clear a buffer.
void free_buff(buffheader_T *buf)
{
buffblock_T *p, *np;
@@ -162,7 +156,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,23 +173,19 @@ char_u *get_recorded(void)
char_u *p;
size_t len;
- p = get_buffcont(&recordbuff, TRUE);
+ p = get_buffcont(&recordbuff, true);
free_buff(&recordbuff);
- /*
- * Remove the characters that were added the last time, these must be the
- * (possibly mapped) characters that stopped the recording.
- */
+ // Remove the characters that were added the last time, these must be the
+ // (possibly mapped) characters that stopped the recording.
len = STRLEN(p);
if (len >= last_recorded_len) {
len -= last_recorded_len;
p[len] = NUL;
}
- /*
- * When stopping recording from Insert mode with CTRL-O q, also remove the
- * CTRL-O.
- */
+ // When stopping recording from Insert mode with CTRL-O q, also remove the
+ // CTRL-O.
if (len > 0 && restart_edit != 0 && p[len - 1] == Ctrl_O) {
p[len - 1] = NUL;
}
@@ -207,7 +197,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 +309,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 +331,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) {
@@ -353,9 +343,7 @@ static int read_readbuf(buffheader_T *buf, int advance)
return c;
}
-/*
- * Prepare the read buffers for reading (if they contain something).
- */
+// Prepare the read buffers for reading (if they contain something).
static void start_stuff(void)
{
if (readbuf1.bh_first.b_next != NULL) {
@@ -368,38 +356,30 @@ 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
{
return (readbuf1.bh_first.b_next == NULL);
}
-/*
- * Set a typeahead character that won't be flushed.
- */
+// Set a typeahead character that won't be flushed.
void typeahead_noflush(int c)
{
typeahead_char = c;
}
-/*
- * Remove the contents of the stuff buffer and the mapped characters in the
- * typeahead buffer (used in case of an error). If "flush_typeahead" is true,
- * flush all typeahead characters (used when interrupted by a CTRL-C).
- */
+// Remove the contents of the stuff buffer and the mapped characters in the
+// typeahead buffer (used in case of an error). If "flush_typeahead" is true,
+// flush all typeahead characters (used when interrupted by a CTRL-C).
void flush_buffers(flush_buffers_T flush_typeahead)
{
init_typebuf();
@@ -443,10 +423,8 @@ void beep_flush(void)
}
}
-/*
- * The previous contents of the redo buffer is kept in old_redobuffer.
- * This is used for the CTRL-O <.> command in insert mode.
- */
+// The previous contents of the redo buffer is kept in old_redobuffer.
+// This is used for the CTRL-O <.> command in insert mode.
void ResetRedobuff(void)
{
if (!block_redo) {
@@ -456,10 +434,8 @@ void ResetRedobuff(void)
}
}
-/*
- * Discard the contents of the redo buffer and restore the previous redo
- * buffer.
- */
+// Discard the contents of the redo buffer and restore the previous redo
+// buffer.
void CancelRedo(void)
{
if (!block_redo) {
@@ -565,9 +541,7 @@ void AppendCharToRedobuff(int c)
}
}
-/*
- * Append a number to the redo buffer.
- */
+// Append a number to the redo buffer.
void AppendNumberToRedobuff(long n)
{
if (!block_redo) {
@@ -621,14 +595,40 @@ void stuffcharReadbuff(int c)
add_char_buff(&readbuf1, c);
}
-/*
- * Append a number to the stuff buffer.
- */
+// Append a number to the stuff buffer.
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 +649,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 +670,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
@@ -761,11 +761,9 @@ int start_redo(long count, bool old_redo)
return OK;
}
-/*
- * Repeat the last insert (R, o, O, a, A, i or I command) by stuffing
- * the redo buffer into readbuf2.
- * return FAIL for failure, OK otherwise
- */
+// Repeat the last insert (R, o, O, a, A, i or I command) by stuffing
+// the redo buffer into readbuf2.
+// return FAIL for failure, OK otherwise
int start_redo_ins(void)
{
int c;
@@ -793,14 +791,12 @@ int start_redo_ins(void)
void stop_redo_ins(void)
{
- block_redo = FALSE;
+ block_redo = false;
}
-/*
- * Initialize typebuf.tb_buf to point to typebuf_init.
- * alloc() cannot be used here: In out-of-memory situations it would
- * be impossible to type anything.
- */
+// Initialize typebuf.tb_buf to point to typebuf_init.
+// alloc() cannot be used here: In out-of-memory situations it would
+// be impossible to type anything.
static void init_typebuf(void)
{
if (typebuf.tb_buf == NULL) {
@@ -917,14 +913,12 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent)
val = RM_NONE;
}
- /*
- * Adjust typebuf.tb_noremap[] for the new characters:
- * If noremap == REMAP_NONE or REMAP_SCRIPT: new characters are
- * (sometimes) not remappable
- * If noremap == REMAP_YES: all the new characters are mappable
- * If noremap > 0: "noremap" characters are not remappable, the rest
- * mappable
- */
+ // Adjust typebuf.tb_noremap[] for the new characters:
+ // If noremap == REMAP_NONE or REMAP_SCRIPT: new characters are
+ // (sometimes) not remappable
+ // If noremap == REMAP_YES: all the new characters are mappable
+ // If noremap > 0: "noremap" characters are not remappable, the rest
+ // mappable
if (noremap == REMAP_SKIP) {
nrm = 1;
} else if (noremap < 0) {
@@ -932,9 +926,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 +964,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,28 +980,22 @@ 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
{
return typebuf.tb_maplen == 0;
}
-/*
- * Return the number of characters that are mapped (or not typed).
- */
+// Return the number of characters that are mapped (or not typed).
int typebuf_maplen(void)
FUNC_ATTR_PURE
{
return typebuf.tb_maplen;
}
-/*
- * remove "len" characters from typebuf.tb_buf[typebuf.tb_off + offset]
- */
+// remove "len" characters from typebuf.tb_buf[typebuf.tb_off + offset]
void del_typebuf(int len, int offset)
{
int i;
@@ -1018,21 +1006,14 @@ void del_typebuf(int len, int offset)
typebuf.tb_len -= len;
- /*
- * Easy case: Just increase typebuf.tb_off.
- */
+ // Easy case: Just increase typebuf.tb_off.
if (offset == 0 && typebuf.tb_buflen - (typebuf.tb_off + len)
>= 3 * MAXMAPLEN + 3) {
typebuf.tb_off += len;
- }
- /*
- * Have to move the characters in typebuf.tb_buf[] and typebuf.tb_noremap[]
- */
- else {
+ } else {
+ // Have to move the characters in typebuf.tb_buf[] and typebuf.tb_noremap[]
i = typebuf.tb_off + offset;
- /*
- * Leave some extra room at the end to avoid reallocation.
- */
+ // Leave some extra room at the end to avoid reallocation.
if (typebuf.tb_off > MAXMAPLEN) {
memmove(typebuf.tb_buf + MAXMAPLEN,
typebuf.tb_buf + typebuf.tb_off, (size_t)offset);
@@ -1081,10 +1062,8 @@ void del_typebuf(int len, int offset)
}
}
-/*
- * Write typed characters to script file.
- * If recording is on put the character in the recordbuffer.
- */
+// Write typed characters to script file.
+// If recording is on put the character in the recordbuffer.
static void gotchars(const char_u *chars, size_t len)
FUNC_ATTR_NONNULL_ALL
{
@@ -1141,14 +1120,12 @@ void ungetchars(int len)
}
}
-/*
- * Sync undo. Called when typed characters are obtained from the typeahead
- * buffer, or when a menu is used.
- * Do not sync:
- * - In Insert mode, unless cursor key has been used.
- * - While reading a script file.
- * - When no_u_sync is non-zero.
- */
+// Sync undo. Called when typed characters are obtained from the typeahead
+// buffer, or when a menu is used.
+// Do not sync:
+// - In Insert mode, unless cursor key has been used.
+// - While reading a script file.
+// - When no_u_sync is non-zero.
void may_sync_undo(void)
{
if ((!(State & (MODE_INSERT | MODE_CMDLINE)) || arrow_used)
@@ -1157,9 +1134,7 @@ void may_sync_undo(void)
}
}
-/*
- * Make "typebuf" empty and allocate new buffers.
- */
+// Make "typebuf" empty and allocate new buffers.
void alloc_typebuf(void)
{
typebuf.tb_buf = xmalloc(TYPELEN_INIT);
@@ -1175,9 +1150,7 @@ void alloc_typebuf(void)
}
}
-/*
- * Free the buffers of "typebuf".
- */
+// Free the buffers of "typebuf".
void free_typebuf(void)
{
if (typebuf.tb_buf == typebuf_init) {
@@ -1192,10 +1165,8 @@ void free_typebuf(void)
}
}
-/*
- * When doing ":so! file", the current typeahead needs to be saved, and
- * restored when "file" has been read completely.
- */
+// When doing ":so! file", the current typeahead needs to be saved, and
+// restored when "file" has been read completely.
static typebuf_T saved_typebuf[NSCRIPT];
void save_typebuf(void)
@@ -1219,9 +1190,7 @@ static bool can_get_old_char(void)
return old_char != -1 && (old_KeyStuffed || stuff_empty());
}
-/*
- * Save all three kinds of typeahead, so that the user must type at a prompt.
- */
+// Save all three kinds of typeahead, so that the user must type at a prompt.
void save_typeahead(tasave_T *tp)
{
tp->save_typebuf = typebuf;
@@ -1237,10 +1206,8 @@ void save_typeahead(tasave_T *tp)
readbuf2.bh_first.b_next = NULL;
}
-/*
- * Restore the typeahead to what it was before calling save_typeahead().
- * The allocated memory is freed, can only be called once!
- */
+// Restore the typeahead to what it was before calling save_typeahead().
+// The allocated memory is freed, can only be called once!
void restore_typeahead(tasave_T *tp)
{
if (tp->typebuf_valid) {
@@ -1260,7 +1227,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));
@@ -1294,12 +1261,10 @@ void openscript(char_u *name, bool directly)
}
save_typebuf();
- /*
- * Execute the commands from the file right now when using ":source!"
- * after ":global" or ":argdo" or in a loop. Also when another command
- * follows. This means the display won't be updated. Don't do this
- * always, "make test" would fail.
- */
+ // Execute the commands from the file right now when using ":source!"
+ // after ":global" or ":argdo" or in a loop. Also when another command
+ // follows. This means the display won't be updated. Don't do this
+ // always, "make test" would fail.
if (directly) {
oparg_T oa;
int oldcurscript;
@@ -1328,9 +1293,7 @@ void openscript(char_u *name, bool directly)
}
}
-/*
- * Close the currently active input script.
- */
+// Close the currently active input script.
static void closescript(void)
{
free_typebuf();
@@ -1353,9 +1316,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
{
@@ -1434,10 +1395,8 @@ int vgetc(void)
garbage_collect(false);
}
- /*
- * If a character was put back with vungetc, it was already processed.
- * Return it directly.
- */
+ // If a character was put back with vungetc, it was already processed.
+ // Return it directly.
if (can_get_old_char()) {
c = old_char;
old_char = -1;
@@ -1610,11 +1569,9 @@ int vgetc(void)
last_vgetc_recorded_len = last_recorded_len;
}
- /*
- * In the main loop "may_garbage_collect" can be set to do garbage
- * collection in the first next vgetc(). It's disabled after that to
- * avoid internally used Lists and Dicts to be freed.
- */
+ // In the main loop "may_garbage_collect" can be set to do garbage
+ // collection in the first next vgetc(). It's disabled after that to
+ // avoid internally used Lists and Dicts to be freed.
may_garbage_collect = false;
// Execute Lua on_key callbacks.
@@ -1623,10 +1580,8 @@ int vgetc(void)
return c;
}
-/*
- * Like vgetc(), but never return a NUL when called recursively, get a key
- * directly from the user (ignoring typeahead).
- */
+// Like vgetc(), but never return a NUL when called recursively, get a key
+// directly from the user (ignoring typeahead).
int safe_vgetc(void)
{
int c;
@@ -1638,10 +1593,8 @@ int safe_vgetc(void)
return c;
}
-/*
- * Like safe_vgetc(), but loop to handle K_IGNORE.
- * Also ignore scrollbar events.
- */
+// Like safe_vgetc(), but loop to handle K_IGNORE.
+// Also ignore scrollbar events.
int plain_vgetc(void)
{
int c;
@@ -1654,12 +1607,10 @@ int plain_vgetc(void)
return c;
}
-/*
- * Check if a character is available, such that vgetc() will not block.
- * If the next character is a special character or multi-byte, the returned
- * character is not valid!.
- * Returns NUL if no character is available.
- */
+// Check if a character is available, such that vgetc() will not block.
+// If the next character is a special character or multi-byte, the returned
+// character is not valid!.
+// Returns NUL if no character is available.
int vpeekc(void)
{
if (can_get_old_char()) {
@@ -1668,11 +1619,9 @@ int vpeekc(void)
return vgetorpeek(false);
}
-/*
- * Check if any character is available, also half an escape sequence.
- * Trick: when no typeahead found, but there is something in the typeahead
- * buffer, it must be an ESC that is recognized as the start of a key code.
- */
+// Check if any character is available, also half an escape sequence.
+// Trick: when no typeahead found, but there is something in the typeahead
+// buffer, it must be an ESC that is recognized as the start of a key code.
int vpeekc_any(void)
{
int c;
@@ -1684,10 +1633,8 @@ int vpeekc_any(void)
return c;
}
-/*
- * Call vpeekc() without causing anything to be mapped.
- * Return TRUE if a character is available, FALSE otherwise.
- */
+// Call vpeekc() without causing anything to be mapped.
+// Return true if a character is available, false otherwise.
int char_avail(void)
{
int retval;
@@ -1750,7 +1697,8 @@ 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);
+ clear_cmdline = true;
}
set_vim_var_nr(VV_MOUSE_WIN, 0);
@@ -1760,26 +1708,26 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
rettv->vval.v_number = n;
if (n != 0 && (IS_SPECIAL(n) || mod_mask != 0)) {
- char_u temp[10]; // modifier: 3, mbyte-char: 6, NUL: 1
+ char temp[10]; // modifier: 3, mbyte-char: 6, NUL: 1
int i = 0;
// Turn a special key into three bytes, plus modifier.
if (mod_mask != 0) {
- temp[i++] = K_SPECIAL;
- temp[i++] = KS_MODIFIER;
- temp[i++] = (char_u)mod_mask;
+ temp[i++] = (char)K_SPECIAL;
+ temp[i++] = (char)KS_MODIFIER;
+ temp[i++] = (char)mod_mask;
}
if (IS_SPECIAL(n)) {
- temp[i++] = K_SPECIAL;
- temp[i++] = (char_u)K_SECOND(n);
- temp[i++] = K_THIRD(n);
+ temp[i++] = (char)K_SPECIAL;
+ temp[i++] = (char)K_SECOND(n);
+ temp[i++] = (char)K_THIRD(n);
} else {
- i += utf_char2bytes((int)n, (char *)temp + i);
+ i += utf_char2bytes((int)n, temp + i);
}
assert(i < 10);
temp[i++] = NUL;
rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char *)vim_strsave(temp);
+ rettv->vval.v_string = xstrdup(temp);
if (is_mouse_key((int)n)) {
int row = mouse_row;
@@ -1810,13 +1758,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 +1784,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 +1829,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 +1995,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 +2050,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 +2059,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;
@@ -2188,7 +2135,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
// complete match
if (keylen >= 0 && keylen <= typebuf.tb_len) {
- char_u *map_str = NULL;
+ char *map_str = NULL;
// Write chars to script file(s).
// Note: :lmap mappings are written *after* being applied. #5658
@@ -2228,8 +2175,8 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
char save_m_expr = mp->m_expr;
int save_m_noremap = mp->m_noremap;
char save_m_silent = mp->m_silent;
- char_u *save_m_keys = NULL; // only saved when needed
- char_u *save_m_str = NULL; // only saved when needed
+ char *save_m_keys = NULL; // only saved when needed
+ char *save_m_str = NULL; // only saved when needed
LuaRef save_m_luaref = mp->m_luaref;
// Handle ":map <expr>": evaluate the {rhs} as an
@@ -2246,9 +2193,9 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
vgetc_busy = 0;
may_garbage_collect = false;
- save_m_keys = vim_strsave(mp->m_keys);
+ save_m_keys = xstrdup((char *)mp->m_keys);
if (save_m_luaref == LUA_NOREF) {
- save_m_str = vim_strsave(mp->m_str);
+ save_m_str = xstrdup(mp->m_str);
}
map_str = eval_map_expr(mp, NUL);
@@ -2260,13 +2207,13 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
// If an error was displayed and the expression returns an empty
// string, generate a <Nop> to allow for a redraw.
if (prev_did_emsg != did_emsg && (map_str == NULL || *map_str == NUL)) {
- char_u buf[4];
+ char buf[4];
xfree(map_str);
- buf[0] = K_SPECIAL;
- buf[1] = KS_EXTRA;
+ buf[0] = (char)K_SPECIAL;
+ buf[1] = (char)KS_EXTRA;
buf[2] = KE_IGNORE;
buf[3] = NUL;
- map_str = vim_strsave(buf);
+ map_str = xstrdup(buf);
if (State & MODE_CMDLINE) {
// redraw the command below the error
msg_didout = true;
@@ -2295,18 +2242,18 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
// If this is a LANGMAP mapping, then we didn't record the keys
// at the start of the function and have to record them now.
if (keylen > typebuf.tb_maplen && (mp->m_mode & MODE_LANGMAP) != 0) {
- gotchars(map_str, STRLEN(map_str));
+ gotchars((char_u *)map_str, STRLEN(map_str));
}
if (save_m_noremap != REMAP_YES) {
noremap = save_m_noremap;
- } else if (STRNCMP(map_str, save_m_keys != NULL ? save_m_keys : mp->m_keys,
+ } else if (STRNCMP(map_str, save_m_keys != NULL ? save_m_keys : (char *)mp->m_keys,
(size_t)keylen) != 0) {
noremap = REMAP_YES;
} else {
noremap = REMAP_SKIP;
}
- i = ins_typebuf((char *)map_str, noremap, 0, true, cmd_silent || save_m_silent);
+ i = ins_typebuf(map_str, noremap, 0, true, cmd_silent || save_m_silent);
if (save_m_expr) {
xfree(map_str);
}
@@ -2364,8 +2311,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 +2399,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 +2448,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 +2477,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 +2495,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;
- ptr = get_cursor_line_ptr();
- while (col < curwin->w_cursor.col) {
- if (!ascii_iswhite(ptr[col])) {
- curwin->w_wcol = vcol;
+ curwin->w_wcol = 0;
+ ptr = (char_u *)get_cursor_line_ptr();
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, curwin,
+ curwin->w_cursor.lnum, 0, (char *)ptr, (char *)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) {
@@ -2574,8 +2526,8 @@ static int vgetorpeek(bool advance)
if (col > 0 && curwin->w_wcol > 0) {
// Correct when the cursor is on the right halve
// of a double-wide character.
- ptr = get_cursor_line_ptr();
- col -= utf_head_off(ptr, ptr + col);
+ ptr = (char_u *)get_cursor_line_ptr();
+ col -= utf_head_off((char *)ptr, (char *)ptr + col);
if (utf_ptr2cells((char *)ptr + col) > 1) {
curwin->w_wcol--;
}
@@ -2829,11 +2781,9 @@ int inchar(char_u *buf, int maxlen, long wait_time)
ui_flush();
}
- /*
- * Don't reset these when at the hit-return prompt, otherwise an endless
- * recursive loop may result (write error in swapfile, hit-return, timeout
- * on char wait, flush swapfile, write error....).
- */
+ // Don't reset these when at the hit-return prompt, otherwise an endless
+ // recursive loop may result (write error in swapfile, hit-return, timeout
+ // on char wait, flush swapfile, write error....).
if (State != MODE_HITRETURN) {
did_outofmem_msg = false; // display out of memory message (again)
did_swapwrite_msg = false; // display swap file write error again
@@ -2866,7 +2816,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 +2879,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..1cd8db6266 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 });
@@ -614,7 +599,7 @@ EXTERN int inhibit_delete_count INIT(= 0);
#define DBCS_DEBUG (-1)
/// Encoding used when 'fencs' is set to "default"
-EXTERN char_u *fenc_default INIT(= NULL);
+EXTERN char *fenc_default INIT(= NULL);
/// "State" is the main state of Vim.
/// There are other variables that modify the state:
@@ -685,8 +670,8 @@ EXTERN bool cmd_silent INIT(= false); // don't echo the command line
EXTERN int swap_exists_action INIT(= SEA_NONE); ///< For dialog when swap file already exists.
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 IObuff[IOSIZE]; ///< Buffer for sprintf, I/O, etc.
+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..63bb945f73 100644
--- a/src/nvim/grid.c
+++ b/src/nvim/grid.c
@@ -46,14 +46,14 @@ void grid_adjust(ScreenGrid **grid, int *row_off, int *col_off)
}
/// Put a unicode char, and up to MAX_MCO composing chars, in a screen cell.
-int schar_from_cc(char_u *p, int c, int u8cc[MAX_MCO])
+int schar_from_cc(char *p, int c, int u8cc[MAX_MCO])
{
- int len = utf_char2bytes(c, (char *)p);
+ int len = utf_char2bytes(c, p);
for (int i = 0; i < MAX_MCO; i++) {
if (u8cc[i] == 0) {
break;
}
- len += utf_char2bytes(u8cc[i], (char *)p + len);
+ len += utf_char2bytes(u8cc[i], p + len);
}
p[len] = 0;
return len;
@@ -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[]".
@@ -140,7 +140,7 @@ void grid_getbytes(ScreenGrid *grid, int row, int col, char_u *bytes, int *attrp
if (grid->chars != NULL && row < grid->rows && col < grid->cols) {
off = grid->line_offset[row] + (size_t)col;
*attrp = grid->attrs[off];
- schar_copy(bytes, grid->chars[off]);
+ schar_copy((char *)bytes, grid->chars[off]);
}
}
@@ -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);
}
@@ -171,7 +171,7 @@ void grid_puts_line_start(ScreenGrid *grid, int row)
put_dirty_grid = grid;
}
-void grid_put_schar(ScreenGrid *grid, int row, int col, char_u *schar, int attr)
+void grid_put_schar(ScreenGrid *grid, int row, int col, char *schar, int attr)
{
assert(put_dirty_row == row);
size_t off = grid->line_offset[row] + (size_t)col;
@@ -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(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/grid.h b/src/nvim/grid.h
index 6a93bf3d90..0e79183c14 100644
--- a/src/nvim/grid.h
+++ b/src/nvim/grid.h
@@ -29,30 +29,30 @@ EXTERN sattr_T *linebuf_attr INIT(= NULL);
// screen grid.
/// Put a ASCII character in a screen cell.
-static inline void schar_from_ascii(char_u *p, const char c)
+static inline void schar_from_ascii(char *p, const char c)
{
- p[0] = (char_u)c;
+ p[0] = c;
p[1] = 0;
}
/// Put a unicode character in a screen cell.
-static inline int schar_from_char(char_u *p, int c)
+static inline int schar_from_char(char *p, int c)
{
- int len = utf_char2bytes(c, (char *)p);
+ int len = utf_char2bytes(c, p);
p[len] = NUL;
return len;
}
/// compare the contents of two screen cells.
-static inline int schar_cmp(char_u *sc1, char_u *sc2)
+static inline int schar_cmp(char *sc1, char *sc2)
{
- return strncmp((char *)sc1, (char *)sc2, sizeof(schar_T));
+ return strncmp(sc1, sc2, sizeof(schar_T));
}
/// copy the contents of screen cell `sc2` into cell `sc1`
-static inline void schar_copy(char_u *sc1, char_u *sc2)
+static inline void schar_copy(char *sc1, char *sc2)
{
- xstrlcpy((char *)sc1, (char *)sc2, sizeof(schar_T));
+ xstrlcpy(sc1, sc2, sizeof(schar_T));
}
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h
index 9252b8a371..57b3817bc6 100644
--- a/src/nvim/grid_defs.h
+++ b/src/nvim/grid_defs.h
@@ -10,7 +10,7 @@
#define MAX_MCO 6 // fixed value for 'maxcombine'
// The characters and attributes drawn on grids.
-typedef char_u schar_T[(MAX_MCO + 1) * 4 + 1];
+typedef char schar_T[(MAX_MCO + 1) * 4 + 1];
typedef int sattr_T;
enum {
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index e8410d1ee7..b530e2c5ec 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -1,19 +1,13 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * hardcopy.c: printing to paper
- */
+// hardcopy.c: printing to paper
#include <assert.h>
#include <inttypes.h>
#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,85 +32,81 @@
#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
- * defined:
- *
- * int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
- * Called once. Code should display printer dialogue (if appropriate) and
- * determine printer font and margin settings. Reset has_color if the printer
- * doesn't support colors at all.
- * Returns FAIL to abort.
- *
- * int mch_print_begin(prt_settings_T *settings)
- * Called to start the print job.
- * 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.
- *
- * int mch_print_end_page()
- * Called at the end of each page.
- * 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.
- *
- * void mch_print_end(prt_settings_T *psettings)
- * Called at normal end of print job.
- *
- * void mch_print_cleanup()
- * Called if print job ends normally or is abandoned. Free any memory, close
- * devices and handles. Also called when mch_print_begin() fails, but not
- * when mch_print_init() fails.
- *
- * void mch_print_set_font(int Bold, int Italic, int Underline);
- * Called whenever the font style changes.
- *
- * void mch_print_set_bg(uint32_t bgcol);
- * Called to set the background color for the following text. Parameter is an
- * RGB value.
- *
- * void mch_print_set_fg(uint32_t fgcol);
- * Called to set the foreground color for the following text. Parameter is an
- * RGB value.
- *
- * 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).
- *
- * 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.
- *
- * 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 },
- }
-;
+// To implement printing on a platform, the following functions must be
+// defined:
+//
+// int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
+// Called once. Code should display printer dialogue (if appropriate) and
+// determine printer font and margin settings. Reset has_color if the printer
+// doesn't support colors at all.
+// Returns FAIL to abort.
+//
+// int mch_print_begin(prt_settings_T *settings)
+// Called to start the print job.
+// 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.
+//
+// int mch_print_end_page()
+// Called at the end of each page.
+// 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.
+//
+// void mch_print_end(prt_settings_T *psettings)
+// Called at normal end of print job.
+//
+// void mch_print_cleanup()
+// Called if print job ends normally or is abandoned. Free any memory, close
+// devices and handles. Also called when mch_print_begin() fails, but not
+// when mch_print_init() fails.
+//
+// void mch_print_set_font(int Bold, int Italic, int Underline);
+// Called whenever the font style changes.
+//
+// void mch_print_set_bg(uint32_t bgcol);
+// Called to set the background color for the following text. Parameter is an
+// RGB value.
+//
+// void mch_print_set_fg(uint32_t fgcol);
+// Called to set the foreground color for the following text. Parameter is an
+// RGB value.
+//
+// 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).
+//
+// 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.
+//
+// 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 const uint32_t cterm_color_8[8] = {
0x000000, 0xff0000, 0x00ff00, 0xffff00,
@@ -152,17 +142,15 @@ 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 },
};
-/*
- * These values determine the print position on a page.
- */
+// These values determine the print position on a page.
typedef struct {
int lead_spaces; // remaining spaces for a TAB
int print_pos; // virtual column for computing TABs
@@ -188,8 +176,8 @@ struct prt_ps_font_S {
char *(ps_fontname[4]);
};
-/* Structures to map user named encoding and mapping to PS equivalents for
- * building CID font name */
+// Structures to map user named encoding and mapping to PS equivalents for
+// building CID font name
struct prt_ps_encoding_S {
char *encoding;
char *cmap_encoding;
@@ -247,8 +235,8 @@ struct prt_dsc_line_S {
int len;
};
-/* Static buffer to read initial comments in a resource file, some can have a
- * couple of KB of comments! */
+// Static buffer to read initial comments in a resource file, some can have a
+// couple of KB of comments!
#define PRT_FILE_BUFFER_LEN (2048)
struct prt_resfile_buffer_S {
char_u buffer[PRT_FILE_BUFFER_LEN];
@@ -261,33 +249,27 @@ struct prt_resfile_buffer_S {
# include "hardcopy.c.generated.h"
#endif
-/*
- * Parse 'printoptions' and set the flags in "printer_opts".
- * Returns an error message or NULL;
- */
+// Parse 'printoptions' and set the flags in "printer_opts".
+// Returns an error message or NULL;
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);
}
-/*
- * Parse 'printoptions' and set the flags in "printer_opts".
- * Returns an error message or NULL;
- */
+// Parse 'printoptions' and set the flags in "printer_opts".
+// Returns an error message or NULL;
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);
}
-/*
- * Parse a list of options in the form
- * option:value,option:value,option:value
- *
- * "value" can start with a number which is parsed out, e.g. margin:12mm
- *
- * Returns an error message for an illegal option, NULL otherwise.
- * Only used for the printer at the moment...
- */
+// Parse a list of options in the form
+// option:value,option:value,option:value
+//
+// "value" can start with a number which is parsed out, e.g. margin:12mm
+//
+// Returns an error message for an illegal option, NULL otherwise.
+// Only used for the printer at the moment...
static char *parse_list_options(char_u *option_str, option_table_T *table, size_t table_size)
{
option_table_T *old_opts;
@@ -307,9 +289,7 @@ static char *parse_list_options(char_u *option_str, option_table_T *table, size_
table[idx].present = false;
}
- /*
- * Repeat for all comma separated parts.
- */
+ // Repeat for all comma separated parts.
stringp = option_str;
while (*stringp) {
colonp = (char_u *)vim_strchr((char *)stringp, ':');
@@ -324,7 +304,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;
}
@@ -367,10 +347,8 @@ static char *parse_list_options(char_u *option_str, option_table_T *table, size_
return ret;
}
-/*
- * If using a dark background, the colors will probably be too bright to show
- * up well on white paper, so reduce their brightness.
- */
+// If using a dark background, the colors will probably be too bright to show
+// up well on white paper, so reduce their brightness.
static uint32_t darken_rgb(uint32_t rgb)
{
return ((rgb >> 17) << 16)
@@ -495,9 +473,7 @@ static void prt_line_number(prt_settings_T *const psettings, const int page_line
}
}
-/*
- * Get the currently effective header height.
- */
+// Get the currently effective header height.
int prt_header_height(void)
{
if (printer_opts[OPT_PRINT_HEADERHEIGHT].present) {
@@ -506,19 +482,15 @@ 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
&& TOLOWER_ASC(printer_opts[OPT_PRINT_NUMBER].string[0]) == 'y';
}
-/*
- * Return the unit used in a margin item in 'printoptions'.
- * Returns PRT_UNIT_NONE if not recognized.
- */
+// Return the unit used in a margin item in 'printoptions'.
+// Returns PRT_UNIT_NONE if not recognized.
int prt_get_unit(int idx)
{
int u = PRT_UNIT_NONE;
@@ -526,7 +498,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,14 +524,12 @@ 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;
-
- /*
- * Need to (temporarily) set current line number and first/last line
- * number on the 'window'. Since we don't know how long the page is,
- * set the first and current line number to the top line, and guess
- * that the page length is 64.
- */
+ int use_sandbox = false;
+
+ // Need to (temporarily) set current line number and first/last line
+ // number on the 'window'. Since we don't know how long the page is,
+ // set the first and current line number to the top line, and guess
+ // that the page length is 64.
tmp_lnum = curwin->w_cursor.lnum;
tmp_topline = curwin->w_topline;
tmp_botline = curwin->w_botline;
@@ -614,14 +584,12 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum, const
}
}
-/*
- * Display a print status message.
- */
+// Display a print status message.
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();
}
@@ -652,13 +620,11 @@ void ex_hardcopy(exarg_T *eap)
settings.arguments = (char_u *)eap->arg;
}
- /*
- * Initialise for printing. Ask the user for settings, unless forceit is
- * set.
- * The mch_print_init() code should set up margins if applicable. (It may
- * not be a real printer - for example the engine might generate HTML or
- * PS.)
- */
+ // Initialise for printing. Ask the user for settings, unless forceit is
+ // set.
+ // The mch_print_init() code should set up margins if applicable. (It may
+ // not be a real printer - for example the engine might generate HTML or
+ // PS.)
if (mch_print_init(&settings,
curbuf->b_fname == NULL ? (char_u *)buf_spname(curbuf) : curbuf->b_sfname ==
NULL ? (char_u *)curbuf->b_fname : (char_u *)curbuf->b_sfname,
@@ -669,7 +635,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 =
@@ -695,9 +661,7 @@ void ex_hardcopy(exarg_T *eap)
prt_get_attr(id, &settings.number, settings.modec);
}
- /*
- * Estimate the total lines to be printed
- */
+ // Estimate the total lines to be printed
for (lnum = eap->line1; lnum <= eap->line2; lnum++) {
bytes_to_print += STRLEN(skipwhite((char *)ml_get(lnum)));
}
@@ -725,9 +689,7 @@ void ex_hardcopy(exarg_T *eap)
goto print_fail_no_begin;
}
- /*
- * Loop over collated copies: 1 2 3, 1 2 3, ...
- */
+ // Loop over collated copies: 1 2 3, 1 2 3, ...
page_count = 0;
for (collated_copies = 0;
collated_copies < settings.n_collated_copies;
@@ -748,27 +710,19 @@ 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, ...
- */
+ // 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 (uncollated_copies = 0;
uncollated_copies < settings.n_uncollated_copies;
uncollated_copies++) {
// Set the print position to the start of this page.
prtpos = page_prtpos;
- /*
- * Do front and rear side of a page.
- */
- for (side = 0; side <= settings.duplex; ++side) {
- /*
- * Print one page.
- */
+ // Do front and rear side of a page.
+ for (side = 0; side <= settings.duplex; side++) {
+ // Print one page.
// Check for interrupt character every page.
os_breakcheck();
@@ -780,7 +734,7 @@ void ex_hardcopy(exarg_T *eap)
sprintf((char *)IObuff, _("Printing page %d (%zu%%)"),
page_count + 1 + side,
prtpos.bytes_printed * 100 / bytes_to_print);
- if (!mch_print_begin_page(IObuff)) {
+ if (!mch_print_begin_page((char_u *)IObuff)) {
goto print_fail;
}
@@ -790,11 +744,9 @@ void ex_hardcopy(exarg_T *eap)
collated_copies + 1,
settings.n_collated_copies);
}
- prt_message(IObuff);
+ prt_message((char_u *)IObuff);
- /*
- * Output header if required
- */
+ // Output header if required
if (prt_header_height() > 0) {
prt_header(&settings, page_count + 1 + side,
prtpos.file_line);
@@ -826,10 +778,8 @@ void ex_hardcopy(exarg_T *eap)
}
}
- /*
- * Extra blank page for duplexing with odd number of pages and
- * more copies to come.
- */
+ // Extra blank page for duplexing with odd number of pages and
+ // more copies to come.
if (prtpos.file_line > eap->line2 && settings.duplex
&& side == 0
&& uncollated_copies + 1 < settings.n_uncollated_copies) {
@@ -848,13 +798,13 @@ void ex_hardcopy(exarg_T *eap)
vim_snprintf((char *)IObuff, IOSIZE, _("Printed: %s"),
settings.jobname);
- prt_message(IObuff);
+ prt_message((char_u *)IObuff);
}
print_fail:
if (got_int || settings.user_abort) {
- sprintf((char *)IObuff, "%s", _("Printing aborted"));
- prt_message(IObuff);
+ snprintf(IObuff, IOSIZE, "%s", _("Printing aborted"));
+ prt_message((char_u *)IObuff);
}
mch_print_end(&settings);
@@ -862,15 +812,13 @@ print_fail_no_begin:
mch_print_cleanup();
}
-/*
- * Print one page line.
- * Return the next column to print, or zero if the line is finished.
- */
+// Print one page line.
+// Return the next column to print, or zero if the line is finished.
static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T *ppos)
{
colnr_T col;
char_u *line;
- int need_break = FALSE;
+ int need_break = false;
int outputlen;
int tab_spaces;
int print_pos;
@@ -883,7 +831,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;
@@ -891,11 +839,9 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
}
mch_print_start_line(false, page_line);
- line = ml_get(ppos->file_line);
+ line = (char_u *)ml_get(ppos->file_line);
- /*
- * Loop over the columns until the end of the file line or right margin.
- */
+ // Loop over the columns until the end of the file line or right margin.
for (col = ppos->column; line[col] != NUL && !need_break; col += outputlen) {
if ((outputlen = utfc_ptr2len((char *)line + col)) < 1) {
outputlen = 1;
@@ -909,7 +855,7 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
id = 0;
}
// Get the line again, a multi-line regexp may invalidate it.
- line = ml_get(ppos->file_line);
+ line = (char_u *)ml_get(ppos->file_line);
if (id != current_syn_id) {
current_syn_id = id;
@@ -920,9 +866,7 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
}
}
- /*
- * Appropriately expand any tabs to spaces.
- */
+ // Appropriately expand any tabs to spaces.
if (line[col] == TAB || tab_spaces != 0) {
if (tab_spaces == 0) {
tab_spaces = tabstop_padding(print_pos,
@@ -946,7 +890,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);
@@ -957,10 +901,8 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
ppos->lead_spaces = tab_spaces;
ppos->print_pos = print_pos;
- /*
- * Start next line of file if we clip lines, or have reached end of the
- * line, unless we are doing a formfeed.
- */
+ // Start next line of file if we clip lines, or have reached end of the
+ // line, unless we are doing a formfeed.
if (!ppos->ff
&& (line[col] == NUL
|| (printer_opts[OPT_PRINT_WRAP].present
@@ -971,34 +913,32 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
return col;
}
-/*
- * PS printer stuff.
- *
- * Sources of information to help maintain the PS printing code:
- *
- * 1. PostScript Language Reference, 3rd Edition,
- * Addison-Wesley, 1999, ISBN 0-201-37922-8
- * 2. PostScript Language Program Design,
- * Addison-Wesley, 1988, ISBN 0-201-14396-8
- * 3. PostScript Tutorial and Cookbook,
- * Addison Wesley, 1985, ISBN 0-201-10179-3
- * 4. PostScript Language Document Structuring Conventions Specification,
- * version 3.0,
- * Adobe Technote 5001, 25th September 1992
- * 5. PostScript Printer Description File Format Specification, Version 4.3,
- * Adobe technote 5003, 9th February 1996
- * 6. Adobe Font Metrics File Format Specification, Version 4.1,
- * Adobe Technote 5007, 7th October 1998
- * 7. Adobe CMap and CIDFont Files Specification, Version 1.0,
- * Adobe Technote 5014, 8th October 1996
- * 8. Adobe CJKV Character Collections and CMaps for CID-Keyed Fonts,
- * Adoboe Technote 5094, 8th September, 2001
- * 9. CJKV Information Processing, 2nd Edition,
- * O'Reilly, 2002, ISBN 1-56592-224-7
- *
- * Some of these documents can be found in PDF form on Adobe's web site -
- * http://www.adobe.com
- */
+// PS printer stuff.
+//
+// Sources of information to help maintain the PS printing code:
+//
+// 1. PostScript Language Reference, 3rd Edition,
+// Addison-Wesley, 1999, ISBN 0-201-37922-8
+// 2. PostScript Language Program Design,
+// Addison-Wesley, 1988, ISBN 0-201-14396-8
+// 3. PostScript Tutorial and Cookbook,
+// Addison Wesley, 1985, ISBN 0-201-10179-3
+// 4. PostScript Language Document Structuring Conventions Specification,
+// version 3.0,
+// Adobe Technote 5001, 25th September 1992
+// 5. PostScript Printer Description File Format Specification, Version 4.3,
+// Adobe technote 5003, 9th February 1996
+// 6. Adobe Font Metrics File Format Specification, Version 4.1,
+// Adobe Technote 5007, 7th October 1998
+// 7. Adobe CMap and CIDFont Files Specification, Version 1.0,
+// Adobe Technote 5014, 8th October 1996
+// 8. Adobe CJKV Character Collections and CMaps for CID-Keyed Fonts,
+// Adoboe Technote 5094, 8th September, 2001
+// 9. CJKV Information Processing, 2nd Edition,
+// O'Reilly, 2002, ISBN 1-56592-224-7
+//
+// Some of these documents can be found in PDF form on Adobe's web site -
+// http://www.adobe.com
#define PRT_PS_DEFAULT_DPI (72) // Default user space resolution
#define PRT_PS_DEFAULT_FONTSIZE (10)
@@ -1222,16 +1162,15 @@ static struct prt_ps_mbfont_S prt_ps_mbfonts[] =
}
};
-/* The PS prolog file version number has to match - if the prolog file is
- * updated, increment the number in the file and here. Version checking was
- * added as of VIM 6.2.
- * The CID prolog file version number behaves as per PS prolog.
- * Table of VIM and prolog versions:
- *
- * VIM Prolog CIDProlog
- * 6.2 1.3
- * 7.0 1.4 1.0
- */
+// The PS prolog file version number has to match - if the prolog file is
+// updated, increment the number in the file and here. Version checking was
+// added as of VIM 6.2.
+// The CID prolog file version number behaves as per PS prolog.
+// Table of VIM and prolog versions:
+//
+// VIM Prolog CIDProlog
+// 6.2 1.3
+// 7.0 1.4 1.0
#define PRT_PROLOG_VERSION ((char_u *)"1.4")
#define PRT_CID_PROLOG_VERSION ((char_u *)"1.0")
@@ -1242,8 +1181,8 @@ static struct prt_ps_mbfont_S prt_ps_mbfonts[] =
#define PRT_RESOURCE_ENCODING "Encoding"
#define PRT_RESOURCE_CMAP "CMap"
-/* Data for table based DSC comment recognition, easy to extend if VIM needs to
- * read more comments. */
+// Data for table based DSC comment recognition, easy to extend if VIM needs to
+// read more comments.
#define PRT_DSC_MISC_TYPE (-1)
#define PRT_DSC_TITLE_TYPE (1)
#define PRT_DSC_VERSION_TYPE (2)
@@ -1263,17 +1202,13 @@ static struct prt_dsc_comment_S prt_dsc_table[] =
PRT_DSC_ENDCOMMENTS_TYPE }
};
-/*
- * Variables for the output PostScript file.
- */
+// Variables for the output PostScript file.
static FILE *prt_ps_fd;
static bool prt_file_error;
static char_u *prt_ps_file_name = NULL;
-/*
- * Various offsets and dimensions in default PostScript user space (points).
- * Used for text positioning calculations
- */
+// Various offsets and dimensions in default PostScript user space (points).
+// Used for text positioning calculations
static double prt_page_width;
static double prt_page_height;
static double prt_left_margin;
@@ -1288,10 +1223,8 @@ static double prt_bgcol_offset;
static double prt_pos_x_moveto = 0.0;
static double prt_pos_y_moveto = 0.0;
-/*
- * Various control variables used to decide when and how to change the
- * PostScript graphics state.
- */
+// Various control variables used to decide when and how to change the
+// PostScript graphics state.
static bool prt_need_moveto;
static bool prt_do_moveto;
static bool prt_need_font;
@@ -1310,9 +1243,7 @@ static double prt_text_run;
static int prt_page_num;
static int prt_bufsiz;
-/*
- * Variables controlling physical printing.
- */
+// Variables controlling physical printing.
static int prt_media;
static int prt_portrait;
static int prt_num_copies;
@@ -1320,9 +1251,7 @@ static int prt_duplex;
static int prt_tumble;
static int prt_collate;
-/*
- * Buffers used when generating PostScript output
- */
+// Buffers used when generating PostScript output
static char prt_line_buffer[257];
static garray_T prt_ps_buffer = GA_EMPTY_INIT_VALUE;
@@ -1357,36 +1286,28 @@ static void prt_write_file_len(char_u *buffer, size_t bytes)
prt_write_file_raw_len(buffer, bytes);
}
-/*
- * Write a string.
- */
+// Write a string.
static void prt_write_string(char *s)
{
vim_snprintf(prt_line_buffer, sizeof(prt_line_buffer), "%s", s);
prt_write_file(prt_line_buffer);
}
-/*
- * Write an int and a space.
- */
+// Write an int and a space.
static void prt_write_int(int i)
{
snprintf(prt_line_buffer, sizeof(prt_line_buffer), "%d ", i);
prt_write_file(prt_line_buffer);
}
-/*
- * Write a boolean and a space.
- */
+// Write a boolean and a space.
static void prt_write_boolean(int b)
{
snprintf(prt_line_buffer, sizeof(prt_line_buffer), "%s ", (b ? "T" : "F"));
prt_write_file(prt_line_buffer);
}
-/*
- * Write PostScript to re-encode and define the font.
- */
+// Write PostScript to re-encode and define the font.
static void prt_def_font(char *new_name, char *encoding, int height, char *font)
{
vim_snprintf(prt_line_buffer, sizeof(prt_line_buffer),
@@ -1402,9 +1323,7 @@ static void prt_def_font(char *new_name, char *encoding, int height, char *font)
prt_write_file(prt_line_buffer);
}
-/*
- * Write a line to define the CID font.
- */
+// Write a line to define the CID font.
static void prt_def_cidfont(char *new_name, int height, char *cidfont)
{
vim_snprintf(prt_line_buffer, sizeof(prt_line_buffer),
@@ -1415,9 +1334,7 @@ static void prt_def_cidfont(char *new_name, int height, char *cidfont)
prt_write_file(prt_line_buffer);
}
-/*
- * Write a line to define a duplicate of a CID font
- */
+// Write a line to define a duplicate of a CID font
static void prt_dup_cidfont(char *original_name, char *new_name)
{
vim_snprintf(prt_line_buffer, sizeof(prt_line_buffer),
@@ -1425,11 +1342,9 @@ static void prt_dup_cidfont(char *original_name, char *new_name)
prt_write_file(prt_line_buffer);
}
-/*
- * Convert a real value into an integer and fractional part as integers, with
- * the fractional part being in the range [0,10^precision). The fractional part
- * is also rounded based on the precision + 1'th fractional digit.
- */
+// Convert a real value into an integer and fractional part as integers, with
+// the fractional part being in the range [0,10^precision). The fractional part
+// is also rounded based on the precision + 1'th fractional digit.
static void prt_real_bits(double real, int precision, int *pinteger, int *pfraction)
{
int integer = (int)real;
@@ -1445,11 +1360,9 @@ static void prt_real_bits(double real, int precision, int *pinteger, int *pfract
*pfraction = (int)(fraction + 0.5);
}
-/*
- * Write a real and a space. Save bytes if real value has no fractional part!
- * We use prt_real_bits() as %f in sprintf uses the locale setting to decide
- * what decimal point character to use, but PS always requires a '.'.
- */
+// Write a real and a space. Save bytes if real value has no fractional part!
+// We use prt_real_bits() as %f in sprintf uses the locale setting to decide
+// what decimal point character to use, but PS always requires a '.'.
static void prt_write_real(double val, int prec)
{
int integer;
@@ -1475,9 +1388,7 @@ static void prt_write_real(double val, int prec)
prt_write_file(prt_line_buffer);
}
-/*
- * Write a line to define a numeric variable.
- */
+// Write a line to define a numeric variable.
static void prt_def_var(char *name, double value, int prec)
{
vim_snprintf(prt_line_buffer, sizeof(prt_line_buffer),
@@ -1582,8 +1493,8 @@ static int prt_find_resource(char *name, struct prt_ps_resource_S *resource)
// Look for named resource file in runtimepath
STRCPY(buffer, "print");
add_pathsep(buffer);
- STRLCAT(buffer, name, MAXPATHL);
- STRLCAT(buffer, ".ps", MAXPATHL);
+ xstrlcat(buffer, name, MAXPATHL);
+ xstrlcat(buffer, ".ps", MAXPATHL);
resource->filename[0] = NUL;
retval = (do_in_runtimepath(buffer, 0, prt_resource_name, resource->filename)
&& resource->filename[0] != NUL);
@@ -1661,8 +1572,9 @@ static int prt_resfile_skip_ws(int offset)
return -1;
}
-/* prt_next_dsc() - returns detail on next DSC comment line found. Returns true
- * if a DSC comment is found, else false */
+/// Returns detail on next DSC comment line found.
+///
+/// @return true if a DSC comment is found, else false
static bool prt_next_dsc(struct prt_dsc_line_S *p_dsc_line)
FUNC_ATTR_NONNULL_ALL
{
@@ -1988,7 +1900,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);
@@ -2032,9 +1944,7 @@ static double to_device_units(int idx, double physsize, int def_number)
return ret;
}
-/*
- * Calculate margins for given width and height from printoptions settings.
- */
+// Calculate margins for given width and height from printoptions settings.
static void prt_page_margins(double width, double height, double *left, double *right, double *top,
double *bottom)
{
@@ -2074,18 +1984,14 @@ static void prt_build_cid_fontname(int font, char_u *name, int name_len)
prt_ps_mb_font.ps_fontname[font] = fontname;
}
-/*
- * Get number of lines of text that fit on a page (excluding the header).
- */
+// Get number of lines of text that fit on a page (excluding the header).
static int prt_get_lpp(void)
{
int lpp;
- /*
- * Calculate offset to lower left corner of background rect based on actual
- * font height (based on its bounding box) and the line height, handling the
- * case where the font height can exceed the line height.
- */
+ // Calculate offset to lower left corner of background rect based on actual
+ // font height (based on its bounding box) and the line height, handling the
+ // case where the font height can exceed the line height.
prt_bgcol_offset = PRT_PS_FONT_TO_USER(prt_line_height,
prt_ps_font->bbox_min_y);
if ((prt_ps_font->bbox_max_y - prt_ps_font->bbox_min_y) < 1000.0) {
@@ -2120,11 +2026,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 +2049,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 +2065,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 +2091,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,13 +2184,11 @@ 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;
}
- /*
- * Find the size of the paper and set the margins.
- */
+ // Find the size of the paper and set the margins.
prt_portrait = (!printer_opts[OPT_PRINT_PORTRAIT].present
|| TOLOWER_ASC(printer_opts[OPT_PRINT_PORTRAIT].string[0]) ==
'y');
@@ -2298,7 +2199,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) {
@@ -2310,13 +2211,11 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
}
prt_media = i;
- /*
- * Set PS pagesize based on media dimensions and print orientation.
- * Note: Media and page sizes have defined meanings in PostScript and should
- * be kept distinct. Media is the paper (or transparency, or ...) that is
- * printed on, whereas the page size is the area that the PostScript
- * interpreter renders into.
- */
+ // Set PS pagesize based on media dimensions and print orientation.
+ // Note: Media and page sizes have defined meanings in PostScript and should
+ // be kept distinct. Media is the paper (or transparency, or ...) that is
+ // printed on, whereas the page size is the area that the PostScript
+ // interpreter renders into.
if (prt_portrait) {
prt_page_width = prt_mediasize[i].width;
prt_page_height = prt_mediasize[i].height;
@@ -2335,21 +2234,17 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
prt_top_margin = top;
prt_bottom_margin = bottom;
- /*
- * Set up the font size.
- */
+ // 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);
}
}
prt_font_metrics(fontsize);
- /*
- * Return the number of characters per line, and lines per page for the
- * generic print code.
- */
+ // Return the number of characters per line, and lines per page for the
+ // generic print code.
psettings->chars_per_line = prt_get_cpl();
psettings->lines_per_page = prt_get_lpp();
@@ -2358,12 +2253,10 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
return FAIL;
}
- /*
- * Sort out the number of copies to be printed. PS by default will do
- * uncollated copies for you, so once we know how many uncollated copies are
- * wanted cache it away and lie to the generic code that we only want one
- * uncollated copy.
- */
+ // Sort out the number of copies to be printed. PS by default will do
+ // uncollated copies for you, so once we know how many uncollated copies are
+ // wanted cache it away and lie to the generic code that we only want one
+ // uncollated copy.
psettings->n_collated_copies = 1;
psettings->n_uncollated_copies = 1;
prt_num_copies = 1;
@@ -2379,20 +2272,18 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
psettings->jobname = jobname;
- /*
- * 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;
+ // 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;
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;
}
}
@@ -2401,7 +2292,7 @@ int mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
// If the user didn't specify a file name, use a temp file.
if (psettings->outfile == NULL) {
- prt_ps_file_name = vim_tempname();
+ prt_ps_file_name = (char_u *)vim_tempname();
if (prt_ps_file_name == NULL) {
emsg(_(e_notmp));
return FAIL;
@@ -2506,9 +2397,7 @@ bool mch_print_begin(prt_settings_T *psettings)
struct prt_ps_resource_S res_cidfont;
struct prt_ps_resource_S res_cmap;
- /*
- * PS DSC Header comments - no PS code!
- */
+ // PS DSC Header comments - no PS code!
prt_dsc_start();
prt_dsc_textline("Title", (char *)psettings->jobname);
if (os_get_username(buffer, 256) == FAIL) {
@@ -2603,13 +2492,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 +2518,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 +2538,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;
@@ -2700,9 +2589,7 @@ bool mch_print_begin(prt_settings_T *psettings)
prt_num_copies);
prt_dsc_noarg("EndComments");
- /*
- * PS Document page defaults
- */
+ // PS Document page defaults
prt_dsc_noarg("BeginDefaults");
// List font resources most likely common to all pages
@@ -2722,9 +2609,7 @@ bool mch_print_begin(prt_settings_T *psettings)
prt_dsc_noarg("EndDefaults");
- /*
- * PS Document prolog inclusion - all required procsets.
- */
+ // PS Document prolog inclusion - all required procsets.
prt_dsc_noarg("BeginProlog");
// Add required procsets - NOTE: order is important!
@@ -2751,9 +2636,7 @@ bool mch_print_begin(prt_settings_T *psettings)
prt_dsc_noarg("EndProlog");
- /*
- * PS Document setup - must appear after the prolog
- */
+ // PS Document setup - must appear after the prolog
prt_dsc_noarg("BeginSetup");
// Device setup - page size and number of uncollated copies
@@ -2862,9 +2745,7 @@ void mch_print_end(prt_settings_T *psettings)
{
prt_dsc_noarg("Trailer");
- /*
- * Output any info we don't know in toto until we finish
- */
+ // Output any info we don't know in toto until we finish
prt_dsc_ints("Pages", 1, &prt_page_num);
prt_dsc_noarg("EOF");
@@ -2945,7 +2826,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 +2958,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/hardcopy.h b/src/nvim/hardcopy.h
index 9ef4eb0074..ce562cd3e6 100644
--- a/src/nvim/hardcopy.h
+++ b/src/nvim/hardcopy.h
@@ -8,9 +8,7 @@
#include "nvim/globals.h" // for TriState
#include "nvim/types.h" // for char_u
-/*
- * Structure to hold printing color and font attributes.
- */
+// Structure to hold printing color and font attributes.
typedef struct {
uint32_t fg_color;
uint32_t bg_color;
@@ -23,9 +21,7 @@ typedef struct {
int underdashed;
} prt_text_attr_T;
-/*
- * Structure passed back to the generic printer code.
- */
+// Structure passed back to the generic printer code.
typedef struct {
int n_collated_copies;
int n_uncollated_copies;
@@ -42,9 +38,7 @@ typedef struct {
char_u *arguments;
} prt_settings_T;
-/*
- * Generic option table item, only used for printer at the moment.
- */
+// Generic option table item, only used for printer at the moment.
typedef struct {
const char *name;
int hasnum;
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..507c5904b3 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;
}
@@ -180,7 +180,7 @@ void ex_help(exarg_T *eap)
// It is needed for do_tag top open folds under the cursor.
KeyTyped = old_KeyTyped;
- do_tag((char_u *)tag, DT_HELP, 1, false, true);
+ do_tag(tag, DT_HELP, 1, false, true);
// Delete the empty buffer if we're not using it. Careful: autocommands
// may have jumped to another window, check that the buffer is not in a
@@ -367,7 +367,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// the table, it is taken literally (but ~ is escaped). Otherwise '?'
// is recognized as a wildcard.
for (i = (int)ARRAY_SIZE(expr_table); --i >= 0;) {
- if (STRCMP(arg + 5, expr_table[i]) == 0) {
+ if (strcmp(arg + 5, expr_table[i]) == 0) {
for (int si = 0, di = 0;; si++) {
if (arg[si] == '~') {
d[di++] = '\\';
@@ -384,7 +384,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// Recognize a few exceptions to the rule. Some strings that contain
// '*'are changed to "star", otherwise '*' is recognized as a wildcard.
for (i = 0; except_tbl[i][0] != NULL; i++) {
- if (STRCMP(arg, except_tbl[i][0]) == 0) {
+ if (strcmp(arg, except_tbl[i][0]) == 0) {
STRCPY(d, except_tbl[i][1]);
break;
}
@@ -428,7 +428,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// completion.
// Insert a backslash before '~', '$' and '.' to avoid their
// special meaning.
- if ((char_u *)d - IObuff > IOSIZE - 10) { // getting too long!?
+ if (d - IObuff > IOSIZE - 10) { // getting too long!?
break;
}
switch (*s) {
@@ -459,7 +459,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
if (*s < ' '
|| (*s == '^' && s[1]
&& (ASCII_ISALPHA(s[1]) || vim_strchr("?@[\\]^", s[1]) != NULL))) {
- if ((char_u *)d > IObuff && d[-1] != '_' && d[-1] != '\\') {
+ if (d > IObuff && d[-1] != '_' && d[-1] != '\\') {
*d++ = '_'; // prepend a '_' to make x_CTRL-x
}
STRCPY(d, "CTRL-");
@@ -513,15 +513,15 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
*d = NUL;
if (*IObuff == '`') {
- if ((char_u *)d > IObuff + 2 && d[-1] == '`') {
+ if (d > IObuff + 2 && d[-1] == '`') {
// remove the backticks from `command`
memmove(IObuff, IObuff + 1, STRLEN(IObuff));
d[-2] = NUL;
- } else if ((char_u *)d > IObuff + 3 && d[-2] == '`' && d[-1] == ',') {
+ } else if (d > IObuff + 3 && d[-2] == '`' && d[-1] == ',') {
// remove the backticks and comma from `command`,
memmove(IObuff, IObuff + 1, STRLEN(IObuff));
d[-3] = NUL;
- } else if ((char_u *)d > IObuff + 4 && d[-3] == '`'
+ } else if (d > IObuff + 4 && d[-3] == '`'
&& d[-2] == '\\' && d[-1] == '.') {
// remove the backticks and dot from `command`\.
memmove(IObuff, IObuff + 1, STRLEN(IObuff));
@@ -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.
@@ -556,8 +556,8 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
/// tag matches it. Otherwise remove "@en" if "en" is the only language.
void cleanup_help_tags(int num_file, char **file)
{
- char_u buf[4];
- char_u *p = buf;
+ char buf[4];
+ char_u *p = (char_u *)buf;
if (p_hlg[0] != NUL && (p_hlg[0] != 'e' || p_hlg[1] != 'n')) {
*p++ = '@';
@@ -571,7 +571,7 @@ void cleanup_help_tags(int num_file, char **file)
if (len <= 0) {
continue;
}
- if (STRCMP(file[i] + len, "@en") == 0) {
+ if (strcmp(file[i] + len, "@en") == 0) {
// Sorting on priority means the same item in another language may
// be anywhere. Search all items for a match up to the "@en".
int j;
@@ -595,7 +595,7 @@ void cleanup_help_tags(int num_file, char **file)
if (len <= 0) {
continue;
}
- if (STRCMP(file[i] + len, buf) == 0) {
+ if (strcmp(file[i] + len, buf) == 0) {
// remove the default language
file[i][len] = NUL;
}
@@ -615,7 +615,7 @@ void prepare_help_buffer(void)
// latin1 word characters (for translated help files).
// Only set it when needed, buf_init_chartab() is some work.
char *p = "!-~,^*,^|,^\",192-255";
- if (STRCMP(curbuf->b_p_isk, p) != 0) {
+ if (strcmp(curbuf->b_p_isk, p) != 0) {
set_string_option_direct("isk", -1, p, OPT_FREE|OPT_LOCAL, 0);
check_buf_options(curbuf);
(void)buf_init_chartab(curbuf, false);
@@ -650,21 +650,21 @@ void fix_help_buffer(void)
bool in_example = false;
// Set filetype to "help".
- if (STRCMP(curbuf->b_p_ft, "help") != 0) {
+ 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--;
}
if (!syntax_present(curwin)) {
for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) {
- line = (char *)ml_get_buf(curbuf, lnum, false);
+ line = ml_get_buf(curbuf, lnum, false);
const size_t len = STRLEN(line);
if (in_example && len > 0 && !ascii_iswhite(line[0])) {
// End of example: non-white or '<' in first column.
if (line[0] == '<') {
// blank-out a '<' in the first column
- line = (char *)ml_get_buf(curbuf, lnum, true);
+ line = ml_get_buf(curbuf, lnum, true);
line[0] = ' ';
}
in_example = false;
@@ -672,12 +672,12 @@ void fix_help_buffer(void)
if (!in_example && len > 0) {
if (line[len - 1] == '>' && (len == 1 || line[len - 2] == ' ')) {
// blank-out a '>' in the last column (start of example)
- line = (char *)ml_get_buf(curbuf, lnum, true);
+ line = ml_get_buf(curbuf, lnum, true);
line[len - 1] = ' ';
in_example = true;
} else if (line[len - 1] == '~') {
// blank-out a '~' at the end of line (header marker)
- line = (char *)ml_get_buf(curbuf, lnum, true);
+ line = ml_get_buf(curbuf, lnum, true);
line[len - 1] = ' ';
}
}
@@ -687,21 +687,21 @@ void fix_help_buffer(void)
// In the "help.txt" and "help.abx" file, add the locally added help
// files. This uses the very first line in the help file.
char *const fname = path_tail(curbuf->b_fname);
- if (FNAMECMP(fname, "help.txt") == 0
- || (FNAMENCMP(fname, "help.", 5) == 0
+ if (path_fnamecmp(fname, "help.txt") == 0
+ || (path_fnamencmp(fname, "help.", 5) == 0
&& ASCII_ISALPHA(fname[5])
&& ASCII_ISALPHA(fname[6])
&& TOLOWER_ASC(fname[7]) == 'x'
&& fname[8] == NUL)) {
for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; lnum++) {
- line = (char *)ml_get_buf(curbuf, lnum, false);
+ line = ml_get_buf(curbuf, lnum, false);
if (strstr(line, "*local-additions*") == NULL) {
continue;
}
// 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");
@@ -715,8 +715,8 @@ void fix_help_buffer(void)
// Find all "doc/ *.txt" files in this directory.
if (!add_pathsep((char *)NameBuff)
- || STRLCAT(NameBuff, "doc/*.??[tx]", // NOLINT
- sizeof(NameBuff)) >= MAXPATHL) {
+ || xstrlcat(NameBuff, "doc/*.??[tx]", // NOLINT
+ sizeof(NameBuff)) >= MAXPATHL) {
emsg(_(e_fnametoolong));
continue;
}
@@ -741,23 +741,23 @@ 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;
}
- if (FNAMECMP(e1, ".txt") != 0
- && FNAMECMP(e1, fname + 4) != 0) {
+ if (path_fnamecmp(e1, ".txt") != 0
+ && path_fnamecmp(e1, fname + 4) != 0) {
// Not .txt and not .abx, remove it.
XFREE_CLEAR(fnames[i1]);
continue;
}
if (e1 - f1 != e2 - f2
- || FNAMENCMP(f1, f2, e1 - f1) != 0) {
+ || path_fnamencmp(f1, f2, (size_t)(e1 - f1)) != 0) {
continue;
}
- if (FNAMECMP(e1, ".txt") == 0
- && FNAMECMP(e2, fname + 4) == 0) {
+ if (path_fnamecmp(e1, ".txt") == 0
+ && path_fnamecmp(e2, fname + 4) == 0) {
// use .abx instead of .txt
XFREE_CLEAR(fnames[i1]);
}
@@ -772,7 +772,7 @@ void fix_help_buffer(void)
if (fd == NULL) {
continue;
}
- vim_fgets(IObuff, IOSIZE, fd);
+ vim_fgets((char_u *)IObuff, IOSIZE, fd);
if (IObuff[0] == '*'
&& (s = vim_strchr((char *)IObuff + 1, '*'))
!= NULL) {
@@ -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;
}
@@ -819,7 +819,7 @@ void fix_help_buffer(void)
convert_setup(&vc, NULL, NULL);
ml_append(lnum, cp, (colnr_T)0, false);
- if ((char_u *)cp != IObuff) {
+ if (cp != IObuff) {
xfree(cp);
}
lnum++;
@@ -871,8 +871,8 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// Find all *.txt files.
size_t dirlen = STRLCPY(NameBuff, dir, sizeof(NameBuff));
if (dirlen >= MAXPATHL
- || STRLCAT(NameBuff, "/**/*", sizeof(NameBuff)) >= MAXPATHL // NOLINT
- || STRLCAT(NameBuff, ext, sizeof(NameBuff)) >= MAXPATHL) {
+ || xstrlcat(NameBuff, "/**/*", sizeof(NameBuff)) >= MAXPATHL // NOLINT
+ || xstrlcat(NameBuff, ext, sizeof(NameBuff)) >= MAXPATHL) {
emsg(_(e_fnametoolong));
return;
}
@@ -896,7 +896,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// Do this before scanning through all the files.
memcpy(NameBuff, dir, dirlen + 1);
if (!add_pathsep((char *)NameBuff)
- || STRLCAT(NameBuff, tagfname, sizeof(NameBuff)) >= MAXPATHL) {
+ || xstrlcat(NameBuff, tagfname, sizeof(NameBuff)) >= MAXPATHL) {
emsg(_(e_fnametoolong));
return;
}
@@ -931,7 +931,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
const char *const fname = files[fi] + dirlen + 1;
bool firstline = true;
- while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) {
+ while (!vim_fgets((char_u *)IObuff, IOSIZE, fd) && !got_int) {
if (firstline) {
// Detect utf-8 file by a non-ASCII char in the first line.
TriState this_utf8 = kNone;
@@ -974,7 +974,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// characters, there is white space before it and is
// followed by a white character or end-of-line.
if (s == p2
- && ((char_u *)p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t')
+ && (p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t')
&& (vim_strchr(" \t\n\r", s[1]) != NULL
|| s[1] == '\0')) {
*p2 = '\0';
@@ -1067,7 +1067,7 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr)
// Get a list of all files in the help directory and in subdirectories.
STRLCPY(NameBuff, dirname, sizeof(NameBuff));
if (!add_pathsep((char *)NameBuff)
- || STRLCAT(NameBuff, "**", sizeof(NameBuff)) >= MAXPATHL) {
+ || xstrlcat(NameBuff, "**", sizeof(NameBuff)) >= MAXPATHL) {
emsg(_(e_fnametoolong));
return;
}
@@ -1162,14 +1162,13 @@ void ex_helptags(exarg_T *eap)
eap->arg = skipwhite(eap->arg + 3);
}
- if (STRCMP(eap->arg, "ALL") == 0) {
+ if (strcmp(eap->arg, "ALL") == 0) {
do_in_path(p_rtp, "doc", DIP_ALL + DIP_DIR, helptags_cb, &add_help_tags);
} else {
ExpandInit(&xpc);
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)) {
+ dirname = ExpandOne(&xpc, eap->arg, NULL, WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
+ 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..e42cb66422 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
@@ -788,7 +788,7 @@ HlAttrs syn_attr2entry(int attr)
}
/// Gets highlight description for id `attr_id` as a map.
-Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Error *err)
+Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Arena *arena, Error *err)
{
Dictionary dic = ARRAY_DICT_INIT;
@@ -801,25 +801,21 @@ Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Error *err)
"Invalid attribute id: %" PRId64, attr_id);
return dic;
}
-
- return hlattrs2dict(NULL, syn_attr2entry((int)attr_id), rgb);
+ Dictionary retval = arena_dict(arena, HLATTRS_DICT_SIZE);
+ hlattrs2dict(&retval, syn_attr2entry((int)attr_id), rgb);
+ return retval;
}
/// Converts an HlAttrs into Dictionary
///
-/// @param[out] hl optional pre-allocated dictionary for return value
-/// if present, must be allocated with at least 16 elements!
+/// @param[in/out] hl Dictionary with pre-allocated space for HLATTRS_DICT_SIZE elements
/// @param[in] aep data to convert
/// @param use_rgb use 'gui*' settings if true, else resorts to 'cterm*'
-Dictionary hlattrs2dict(Dictionary *hl_alloc, HlAttrs ae, bool use_rgb)
+void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb)
{
+ assert(dict->capacity >= HLATTRS_DICT_SIZE); // at most 16 items
+ Dictionary hl = *dict;
int mask = use_rgb ? ae.rgb_ae_attr : ae.cterm_ae_attr;
- Dictionary hl = ARRAY_DICT_INIT;
- if (hl_alloc) {
- hl = *hl_alloc;
- } else {
- kv_ensure_space(hl, 16);
- }
if (mask & HL_BOLD) {
PUT_C(hl, "bold", BOOLEAN_OBJ(true));
@@ -899,14 +895,7 @@ Dictionary hlattrs2dict(Dictionary *hl_alloc, HlAttrs ae, bool use_rgb)
PUT_C(hl, "blend", INTEGER_OBJ(ae.hl_blend));
}
- if (hl_alloc) {
- *hl_alloc = hl;
- return hl;
- } else {
- Dictionary allocated = copy_dictionary(hl);
- kv_destroy(hl);
- return allocated;
- }
+ *dict = hl;
}
HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *err)
@@ -1086,6 +1075,7 @@ int object_to_color(Object val, char *key, bool rgb, Error *err)
Array hl_inspect(int attr)
{
+ // TODO(bfredl): use arena allocation
Array ret = ARRAY_DICT_INIT;
if (hlstate_active) {
hl_inspect_impl(&ret, attr);
diff --git a/src/nvim/highlight.h b/src/nvim/highlight.h
index 50299bb91c..e85e3859e2 100644
--- a/src/nvim/highlight.h
+++ b/src/nvim/highlight.h
@@ -19,6 +19,8 @@ static inline int win_hl_attr(win_T *wp, int hlf)
return ((wp->w_ns_hl_attr && ns_hl_fast < 0) ? wp->w_ns_hl_attr : hl_attr_active)[hlf];
}
+#define HLATTRS_DICT_SIZE 16
+
#define HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp) \
do { \
bool dark_ = (*p_bg == 'd'); \
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index 77424de3b8..2cb8fabfb4 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,53 @@ static const char *highlight_init_both[] = {
"default link DiagnosticSignWarn DiagnosticWarn",
"default link DiagnosticSignInfo DiagnosticInfo",
"default link DiagnosticSignHint DiagnosticHint",
+
+ "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
};
@@ -504,12 +553,12 @@ void init_highlight(bool both, bool reset)
// Try finding the color scheme file. Used when a color file was loaded
// and 'background' or 't_Co' is changed.
- char_u *p = get_var_value("g:colors_name");
+ char *p = (char *)get_var_value("g:colors_name");
if (p != NULL) {
// Value of g:colors_name could be freed in load_colors() and make
// p invalid, so copy it.
- char_u *copy_p = vim_strsave(p);
- bool okay = load_colors(copy_p);
+ char *copy_p = xstrdup(p);
+ bool okay = load_colors((char_u *)copy_p);
xfree(copy_p);
if (okay) {
return;
@@ -582,7 +631,9 @@ int load_colors(char_u *name)
retval = source_runtime((char *)buf, DIP_START + DIP_OPT);
}
xfree(buf);
- apply_autocmds(EVENT_COLORSCHEME, (char *)name, curbuf->b_fname, false, curbuf);
+ if (retval == OK) {
+ apply_autocmds(EVENT_COLORSCHEME, (char *)name, curbuf->b_fname, false, curbuf);
+ }
recursive = false;
@@ -640,7 +691,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)
{
@@ -740,7 +791,7 @@ void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id)
g->sg_attr = hl_get_syn_attr(0, id, attrs);
// 'Normal' is special
- if (STRCMP(g->sg_name_u, "NORMAL") == 0) {
+ if (strcmp(g->sg_name_u, "NORMAL") == 0) {
cterm_normal_fg_color = g->sg_cterm_fg;
cterm_normal_bg_color = g->sg_cterm_bg;
normal_fg = g->sg_rgb_fg;
@@ -756,7 +807,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 +853,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 +892,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 +944,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 +967,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);
}
@@ -937,7 +988,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// Make a copy so we can check if any attribute actually changed
item_before = hl_table[idx];
- is_normal_group = (STRCMP(hl_table[idx].sg_name_u, "NORMAL") == 0);
+ is_normal_group = (strcmp(hl_table[idx].sg_name_u, "NORMAL") == 0);
// Clear the highlighting for ":hi clear {group}" and ":hi clear".
if (doclear || (forceit && init)) {
@@ -1004,7 +1055,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);
@@ -1068,9 +1119,9 @@ void do_highlight(const char *line, const bool forceit, const bool init)
hl_table[idx].sg_gui = attr;
}
}
- } else if (STRCMP(key, "FONT") == 0) {
+ } else if (strcmp(key, "FONT") == 0) {
// in non-GUI fonts are simply ignored
- } else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) {
+ } else if (strcmp(key, "CTERMFG") == 0 || strcmp(key, "CTERMBG") == 0) {
if (!init || !(hl_table[idx].sg_set & SG_CTERM)) {
if (!init) {
hl_table[idx].sg_set |= SG_CTERM;
@@ -1156,7 +1207,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");
}
}
@@ -1188,7 +1239,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (is_normal_group) {
normal_fg = hl_table[idx].sg_rgb_fg;
}
- } else if (STRCMP(key, "GUIBG") == 0) {
+ } else if (strcmp(key, "GUIBG") == 0) {
int *indexp = &hl_table[idx].sg_rgb_bg_idx;
if (!init || !(hl_table[idx].sg_set & SG_GUI)) {
@@ -1199,7 +1250,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
RgbValue old_color = hl_table[idx].sg_rgb_bg;
int old_idx = hl_table[idx].sg_rgb_bg_idx;
- if (STRCMP(arg, "NONE") != 0) {
+ if (strcmp(arg, "NONE") != 0) {
hl_table[idx].sg_rgb_bg = name_to_color(arg, indexp);
} else {
hl_table[idx].sg_rgb_bg = -1;
@@ -1270,12 +1321,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 +1343,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 +1354,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 +1372,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 +1422,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;
}
@@ -1411,19 +1467,21 @@ static void highlight_list_one(const int id)
}
}
-Dictionary get_global_hl_defs(void)
+Dictionary get_global_hl_defs(Arena *arena)
{
- Dictionary rv = ARRAY_DICT_INIT;
- for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
+ Dictionary rv = arena_dict(arena, (size_t)highlight_ga.ga_len);
+ for (int i = 1; i <= highlight_ga.ga_len; i++) {
Dictionary attrs = ARRAY_DICT_INIT;
HlGroup *h = &hl_table[i - 1];
if (h->sg_attr > 0) {
- attrs = hlattrs2dict(NULL, syn_attr2entry(h->sg_attr), true);
+ attrs = arena_dict(arena, HLATTRS_DICT_SIZE);
+ hlattrs2dict(&attrs, syn_attr2entry(h->sg_attr), true);
} else if (h->sg_link > 0) {
- const char *link = (const char *)hl_table[h->sg_link - 1].sg_name;
- PUT(attrs, "link", STRING_OBJ(cstr_to_string(link)));
+ attrs = arena_dict(arena, 1);
+ char *link = (char *)hl_table[h->sg_link - 1].sg_name;
+ PUT_C(attrs, "link", STRING_OBJ(cstr_as_string(link)));
}
- PUT(rv, (const char *)h->sg_name, DICTIONARY_OBJ(attrs));
+ PUT_C(rv, (char *)h->sg_name, DICTIONARY_OBJ(attrs));
}
return rv;
@@ -1661,7 +1719,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 +1764,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 +1813,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 +1854,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 +1918,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 +2077,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 +2093,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..719899d0b8 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -1,13 +1,11 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * CSCOPE support for Vim added by Andy Kahn <kahn@zk3.dec.com>
- * Ported to Win32 by Sergey Khorev <sergey.khorev@gmail.com>
- *
- * The basic idea/structure of cscope for Vim was borrowed from Nvi. There
- * might be a few lines of code that look similar to what Nvi has.
- */
+// CSCOPE support for Vim added by Andy Kahn <kahn@zk3.dec.com>
+// Ported to Win32 by Sergey Khorev <sergey.khorev@gmail.com>
+//
+// The basic idea/structure of cscope for Vim was borrowed from Nvi. There
+// might be a few lines of code that look similar to what Nvi has.
#include <assert.h>
#include <errno.h>
@@ -78,10 +76,8 @@ static enum {
EXP_CSCOPE_KILL, // expand ":cscope kill" arguments
} expand_what;
-/*
- * Function given to ExpandGeneric() to obtain the cscope command
- * expansion.
- */
+// Function given to ExpandGeneric() to obtain the cscope command
+// expansion.
char *get_cscope_name(expand_T *xp, int idx)
{
int current_idx;
@@ -140,9 +136,7 @@ char *get_cscope_name(expand_T *xp, int idx)
}
}
-/*
- * Handle command line completion for :cscope command.
- */
+// Handle command line completion for :cscope command.
void set_context_in_cscope_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx)
{
// Default: expand subcommands.
@@ -153,10 +147,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 +197,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>"));
@@ -234,16 +228,16 @@ void ex_cstag(exarg_T *eap)
}
if (cs_check_for_tags()) {
- ret = do_tag((char_u *)eap->arg, DT_JUMP, 0, eap->forceit, false);
+ ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, false);
}
}
} else if (cs_check_for_tags()) {
- ret = do_tag((char_u *)eap->arg, DT_JUMP, 0, eap->forceit, false);
+ ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, false);
}
break;
case 1:
if (cs_check_for_tags()) {
- ret = do_tag((char_u *)eap->arg, DT_JUMP, 0, eap->forceit, false);
+ ret = do_tag(eap->arg, DT_JUMP, 0, eap->forceit, false);
if (ret == false) {
if (msg_col) {
msg_putchar('\n');
@@ -278,7 +272,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
{
@@ -304,33 +298,31 @@ void cs_print_tags(void)
cs_manage_matches(NULL, NULL, 0, Print);
}
-/*
- * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
- *
- * Checks for the existence of a |cscope| connection. If no
- * parameters are specified, then the function returns:
- *
- * 0, if cscope was not available (not compiled in), or if there
- * are no cscope connections; or
- * 1, if there is at least one cscope connection.
- *
- * If parameters are specified, then the value of {num}
- * determines how existence of a cscope connection is checked:
- *
- * {num} Description of existence check
- * ----- ------------------------------
- * 0 Same as no parameters (e.g., "cscope_connection()").
- * 1 Ignore {prepend}, and use partial string matches for
- * {dbpath}.
- * 2 Ignore {prepend}, and use exact string matches for
- * {dbpath}.
- * 3 Use {prepend}, use partial string matches for both
- * {dbpath} and {prepend}.
- * 4 Use {prepend}, use exact string matches for both
- * {dbpath} and {prepend}.
- *
- * Note: All string comparisons are case sensitive!
- */
+// "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
+//
+// Checks for the existence of a |cscope| connection. If no
+// parameters are specified, then the function returns:
+//
+// 0, if cscope was not available (not compiled in), or if there
+// are no cscope connections; or
+// 1, if there is at least one cscope connection.
+//
+// If parameters are specified, then the value of {num}
+// determines how existence of a cscope connection is checked:
+//
+// {num} Description of existence check
+// ----- ------------------------------
+// 0 Same as no parameters (e.g., "cscope_connection()").
+// 1 Ignore {prepend}, and use partial string matches for
+// {dbpath}.
+// 2 Ignore {prepend}, and use exact string matches for
+// {dbpath}.
+// 3 Use {prepend}, use partial string matches for both
+// {dbpath} and {prepend}.
+// 4 Use {prepend}, use exact string matches for both
+// {dbpath} and {prepend}.
+//
+// Note: All string comparisons are case sensitive!
bool cs_connection(int num, char_u *dbpath, char_u *ppath)
{
if (num < 0 || num > 4 || (num > 0 && !dbpath)) {
@@ -379,9 +371,8 @@ bool cs_connection(int num, char_u *dbpath, char_u *ppath)
return false;
} // cs_connection
-/*
- * PRIVATE functions
- ****************************************************************************/
+// PRIVATE functions
+// **************************************************************************
/// Add cscope database or a directory name (to look for cscope.out)
/// to the cscope connection list.
@@ -423,7 +414,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,8 +436,8 @@ 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);
- if (!os_path_exists((char_u *)ppath)) {
+ expand_env(arg2, ppath, MAXPATHL);
+ if (!os_path_exists(ppath)) {
goto staterr;
}
}
@@ -684,10 +675,8 @@ static int cs_create_connection(size_t i)
char *prog, *cmd, *ppath = NULL;
#if defined(UNIX)
- /*
- * Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from
- * from_cs[0] and writes to to_cs[1].
- */
+ // Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from
+ // from_cs[0] and writes to to_cs[1].
to_cs[0] = to_cs[1] = from_cs[0] = from_cs[1] = -1;
if (pipe(to_cs) < 0 || pipe(from_cs) < 0) {
(void)emsg(_("E566: Could not create cscope pipes"));
@@ -757,14 +746,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 +828,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 +864,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;
@@ -896,11 +885,9 @@ static int cs_find(exarg_T *eap)
return false;
}
- /*
- * 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) {
+ // Let's replace the NULs written by strtok() with spaces - we need the
+ // spaces to correctly display the quickfix/location list window's title.
+ for (int i = 0; i < eap_arg_len; i++) {
if (NUL == eap->arg[i]) {
eap->arg[i] = ' ';
}
@@ -953,7 +940,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 -
@@ -1016,7 +1003,7 @@ static bool cs_find_common(char *opt, char *pat, int forceit, int verbose, bool
if (qfpos != NULL && *qfpos != '0') {
// Fill error list.
FILE *f;
- char_u *tmp = vim_tempname();
+ char_u *tmp = (char_u *)vim_tempname();
qf_info_T *qi = NULL;
win_T *wp = NULL;
@@ -1041,10 +1028,8 @@ static bool cs_find_common(char *opt, char *pat, int forceit, int verbose, bool
apply_autocmds(EVENT_QUICKFIXCMDPOST, "cscope", curbuf->b_fname, true, curbuf);
if (use_ll) {
- /*
- * In the location list window, use the displayed location
- * list. Otherwise, use the location list for the window.
- */
+ // In the location list window, use the displayed location
+ // list. Otherwise, use the location list for the window.
qi = (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL)
? wp->w_llist_ref : wp->w_llist;
}
@@ -1068,7 +1053,7 @@ static bool cs_find_common(char *opt, char *pat, int forceit, int verbose, bool
(void)cs_manage_matches(matches, contexts, matched, Store);
- return do_tag((char_u *)pat, DT_CSCOPE, 0, forceit, verbose);
+ return do_tag(pat, DT_CSCOPE, 0, forceit, verbose);
}
}
@@ -1106,7 +1091,7 @@ static int cs_help(exarg_T *eap)
cmdp++;
}
- wait_return(TRUE);
+ wait_return(true);
return CSCOPE_SUCCESS;
}
@@ -1280,7 +1265,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
@@ -1431,11 +1416,9 @@ retry:
}
*p = '\0';
- /*
- * cscope output is in the following format:
- *
- * <filename> <context> <line number> <pattern>
- */
+ // cscope output is in the following format:
+ //
+ // <filename> <context> <line number> <pattern>
char *saveptr = NULL;
if ((name = os_strtok(buf, (const char *)" ", &saveptr)) == NULL) {
return NULL;
@@ -1651,7 +1634,7 @@ static void cs_print_tags_priv(char **matches, char **cntxts,
}
(void)snprintf(buf, bufsize, csfmt_str, i + 1, lno);
msg_puts_attr(buf, HL_ATTR(HLF_CM));
- msg_outtrans_long_attr((char_u *)cs_pathcomponents(fname), HL_ATTR(HLF_CM));
+ msg_outtrans_long_attr(cs_pathcomponents(fname), HL_ATTR(HLF_CM));
// compute the required space for the context
char *context = cntxts[i] ? cntxts[i] : globalcntx;
@@ -1673,11 +1656,11 @@ static void cs_print_tags_priv(char **matches, char **cntxts,
msg_putchar('\n');
}
msg_advance(12);
- msg_outtrans_long_attr((char_u *)buf, 0);
+ msg_outtrans_long_attr(buf, 0);
msg_putchar('\n');
if (extra != NULL) {
msg_advance(13);
- msg_outtrans_long_attr((char_u *)extra, 0);
+ msg_outtrans_long_attr(extra, 0);
}
// restore matches[i]
@@ -1786,9 +1769,7 @@ static int cs_read_prompt(size_t i)
}
#if defined(UNIX) && defined(SIGALRM)
-/*
- * Used to catch and ignore SIGALRM below.
- */
+// Used to catch and ignore SIGALRM below.
static void sig_handler(int s)
{
// do nothing
@@ -1838,7 +1819,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) {
@@ -1847,25 +1828,21 @@ static void cs_release_csp(size_t i, bool freefnpp)
os_delay(50L, false); // sleep 50 ms
}
# endif
- /*
- * If the cscope process is still running: kill it.
- * Safety check: If the PID would be zero here, the entire X session
- * would be killed. -1 and 1 are dangerous as well.
- */
+ // If the cscope process is still running: kill it.
+ // Safety check: If the PID would be zero here, the entire X session
+ // would be killed. -1 and 1 are dangerous as well.
if (pid < 0 && csinfo[i].pid > 1) {
# ifdef ECHILD
bool alive = true;
if (waitpid_errno == ECHILD) {
- /*
- * When using 'vim -g', vim is forked and cscope process is
- * no longer a child process but a sibling. So waitpid()
- * fails with errno being ECHILD (No child processes).
- * Don't send SIGKILL to cscope immediately but wait
- * (polling) for it to exit normally as result of sending
- * the "q" command, hence giving it a chance to clean up
- * its temporary files.
- */
+ // When using 'vim -g', vim is forked and cscope process is
+ // no longer a child process but a sibling. So waitpid()
+ // fails with errno being ECHILD (No child processes).
+ // Don't send SIGKILL to cscope immediately but wait
+ // (polling) for it to exit normally as result of sending
+ // the "q" command, hence giving it a chance to clean up
+ // its temporary files.
int waited;
sleep(0);
@@ -1932,7 +1909,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);
}
}
@@ -1974,11 +1951,9 @@ static char *cs_resolve_file(size_t i, char *name)
char *fullname;
char_u *csdir = NULL;
- /*
- * Ppath is freed when we destroy the cscope connection.
- * Fullname is freed after cs_make_vim_style_matches, after it's been
- * copied into the tag buffer used by Vim.
- */
+ // Ppath is freed when we destroy the cscope connection.
+ // Fullname is freed after cs_make_vim_style_matches, after it's been
+ // copied into the tag buffer used by Vim.
size_t len = strlen(name) + 2;
if (csinfo[i].ppath != NULL) {
len += strlen(csinfo[i].ppath);
@@ -2035,7 +2010,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..0f7a5a8e44 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) {
@@ -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;
@@ -452,7 +454,7 @@ int set_indent(int size, int flags)
// characters needed for the indent.
todo = size;
ind_len = 0;
- p = oldline = get_cursor_line_ptr();
+ p = oldline = (char_u *)get_cursor_line_ptr();
// Calculate the buffer size for the new indent, and check to see if it
// isn't already set.
@@ -708,16 +710,16 @@ int get_number_indent(linenr_T lnum)
// In format_lines() (i.e. not insert mode), fo+=q is needed too...
if ((State & MODE_INSERT) || has_format_option(FO_Q_COMS)) {
- lead_len = get_leader_len((char *)ml_get(lnum), NULL, false, true);
+ lead_len = get_leader_len(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;
// vim_regexec() expects a pointer to a line. This lets us
// start matching for the flp beyond any comment leader...
- if (vim_regexec(&regmatch, (char *)ml_get(lnum) + lead_len, (colnr_T)0)) {
+ if (vim_regexec(&regmatch, ml_get(lnum) + lead_len, (colnr_T)0)) {
pos.lnum = lnum;
pos.col = (colnr_T)(*regmatch.endp - ml_get(lnum));
pos.coladd = 0;
@@ -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),
};
@@ -814,7 +857,7 @@ int inindent(int extra)
char_u *ptr;
colnr_T col;
- for (col = 0, ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr); col++) {
+ for (col = 0, ptr = (char_u *)get_cursor_line_ptr(); ascii_iswhite(*ptr); col++) {
ptr++;
}
@@ -831,7 +874,7 @@ bool may_do_si(void)
return curbuf->b_p_si && !curbuf->b_p_cin && *curbuf->b_p_inde == NUL && !p_paste;
}
-// Get indent level from 'indentexpr'.
+/// Get indent level from 'indentexpr'.
int get_expr_indent(void)
{
int indent = -1;
@@ -855,8 +898,8 @@ 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);
- indent = (int)eval_to_number((char *)inde_copy);
+ char *inde_copy = xstrdup(curbuf->b_p_inde);
+ indent = (int)eval_to_number(inde_copy);
xfree(inde_copy);
if (use_sandbox) {
@@ -936,7 +979,7 @@ int get_lisp_indent(void)
continue;
}
- for (that = get_cursor_line_ptr(); *that != NUL; that++) {
+ for (that = (char_u *)get_cursor_line_ptr(); *that != NUL; that++) {
if (*that == ';') {
while (*(that + 1) != NUL) {
that++;
@@ -986,19 +1029,21 @@ int get_lisp_indent(void)
curwin->w_cursor.col = pos->col;
col = pos->col;
- that = get_cursor_line_ptr();
+ that = (char_u *)get_cursor_line_ptr();
if (vi_lisp && (get_indent() == 0)) {
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, (char *)line, (char *)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, (char *)line, (char *)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, (char *)line, (char *)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..c7f37790b6 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -27,11 +27,9 @@ typedef struct {
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "indent_c.c.generated.h"
#endif
-/*
- * Find the start of a comment, not knowing if we are in a comment right now.
- * Search starts at w_cursor.lnum and goes backwards.
- * Return NULL when not inside a comment.
- */
+// Find the start of a comment, not knowing if we are in a comment right now.
+// Search starts at w_cursor.lnum and goes backwards.
+// Return NULL when not inside a comment.
static pos_T *ind_find_start_comment(void) // XXX
{
return find_start_comment(curbuf->b_ind_maxcomment);
@@ -48,11 +46,9 @@ pos_T *find_start_comment(int ind_maxcomment) // XXX
break;
}
- /*
- * Check if the comment start we found is inside a string.
- * If it is then restrict the search to below this line and try again.
- */
- if (!is_pos_in_string(ml_get(pos->lnum), pos->col)) {
+ // Check if the comment start we found is inside a string.
+ // If it is then restrict the search to below this line and try again.
+ if (!is_pos_in_string((char_u *)ml_get(pos->lnum), pos->col)) {
break;
}
cur_maxcomment = curwin->w_cursor.lnum - pos->lnum - 1;
@@ -97,11 +93,9 @@ static pos_T *ind_find_start_CORS(linenr_T *is_raw)
return comment_pos;
}
-/*
- * Find the start of a raw string, not knowing if we are in one right now.
- * Search starts at w_cursor.lnum and goes backwards.
- * Return NULL when not inside a raw string.
- */
+// Find the start of a raw string, not knowing if we are in one right now.
+// Search starts at w_cursor.lnum and goes backwards.
+// Return NULL when not inside a raw string.
static pos_T *find_start_rawstring(int ind_maxcomment) // XXX
{
pos_T *pos;
@@ -115,7 +109,7 @@ static pos_T *find_start_rawstring(int ind_maxcomment) // XXX
// Check if the raw string start we found is inside a string.
// If it is then restrict the search to below this line and try again.
- if (!is_pos_in_string(ml_get(pos->lnum), pos->col)) {
+ if (!is_pos_in_string((char_u *)ml_get(pos->lnum), pos->col)) {
break;
}
cur_maxcomment = curwin->w_cursor.lnum - pos->lnum - 1;
@@ -127,17 +121,13 @@ static pos_T *find_start_rawstring(int ind_maxcomment) // XXX
return pos;
}
-/*
- * Skip to the end of a "string" and a 'c' character.
- * If there is no string or character, return argument unmodified.
- */
+// Skip to the end of a "string" and a 'c' character.
+// If there is no string or character, return argument unmodified.
static const char_u *skip_string(const char_u *p)
{
int i;
- /*
- * We loop, because strings may be concatenated: "date""time".
- */
+ // We loop, because strings may be concatenated: "date""time".
for (;; p++) {
if (p[0] == '\'') { // 'c' or '\n' or '\000'
if (p[1] == NUL) { // ' at end of line
@@ -204,26 +194,21 @@ int is_pos_in_string(const char_u *line, colnr_T col)
return !((colnr_T)(p - line) <= col);
}
-/*
- * Functions for C-indenting.
- * Most of this originally comes from Eric Fischer.
- */
-/*
- * 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)
+// Functions for C-indenting.
+// Most of this originally comes from Eric Fischer.
+
+// 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 *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]))) {
@@ -237,10 +222,8 @@ bool cin_is_cinword(const char_u *line)
return retval;
}
-/*
- * Skip over white space and C comments within the line.
- * Also skip over Perl/shell comments if desired.
- */
+// Skip over white space and C comments within the line.
+// Also skip over Perl/shell comments if desired.
static const char_u *cin_skipcomment(const char_u *s)
{
while (*s) {
@@ -248,8 +231,8 @@ static const char_u *cin_skipcomment(const char_u *s)
s = (char_u *)skipwhite((char *)s);
- /* Perl/shell # comment comment continues until eol. Require a space
- * before # to avoid recognizing $#array. */
+ // Perl/shell # comment comment continues until eol. Require a space
+ // before # to avoid recognizing $#array.
if (curbuf->b_ind_hash_comment != 0 && s != prev_s && *s == '#') {
s += STRLEN(s);
break;
@@ -275,18 +258,14 @@ 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;
}
-/*
- * Check previous lines for a "//" line comment, skipping over blank lines.
- */
+// Check previous lines for a "//" line comment, skipping over blank lines.
static pos_T *find_line_comment(void) // XXX
{
static pos_T pos;
@@ -295,7 +274,7 @@ static pos_T *find_line_comment(void) // XXX
pos = curwin->w_cursor;
while (--pos.lnum > 0) {
- line = ml_get(pos.lnum);
+ line = (char_u *)ml_get(pos.lnum);
p = (char_u *)skipwhite((char *)line);
if (cin_islinecomment(p)) {
pos.col = (int)(p - line);
@@ -359,7 +338,7 @@ static bool cin_islabel_skip(const char_u **s)
// Note: curwin->w_cursor must be where we are looking for the label.
bool cin_islabel(void) // XXX
{
- const char_u *s = cin_skipcomment(get_cursor_line_ptr());
+ const char_u *s = cin_skipcomment((char_u *)get_cursor_line_ptr());
// Exclude "default" from labels, since it should be indented
// like a switch label. Same for C++ scope declarations.
@@ -373,28 +352,24 @@ bool cin_islabel(void) // XXX
return false;
}
- /*
- * Only accept a label if the previous line is terminated or is a case
- * label.
- */
+ // Only accept a label if the previous line is terminated or is a case
+ // label.
pos_T cursor_save;
pos_T *trypos;
const char_u *line;
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
- * it.
- */
+ // If we're in a comment or raw string now, skip to the start of
+ // it.
curwin->w_cursor.col = 0;
if ((trypos = ind_find_start_CORS(NULL)) != NULL) { // XXX
curwin->w_cursor = *trypos;
}
- line = get_cursor_line_ptr();
+ line = (char_u *)get_cursor_line_ptr();
if (cin_ispreproc(line)) { // ignore #defines, #if, etc.
continue;
}
@@ -403,7 +378,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))) {
@@ -415,17 +390,15 @@ bool cin_islabel(void) // XXX
return true; // label at start of file???
}
-/*
- * Recognize structure initialization and enumerations:
- * "[typedef] [static|public|protected|private] enum"
- * "[typedef] [static|public|protected|private] = {"
- */
+// Recognize structure initialization and enumerations:
+// "[typedef] [static|public|protected|private] enum"
+// "[typedef] [static|public|protected|private] = {"
static int cin_isinit(void)
{
const char_u *s;
static char *skip[] = { "static", "public", "protected", "private" };
- s = cin_skipcomment(get_cursor_line_ptr());
+ s = cin_skipcomment((char_u *)get_cursor_line_ptr());
if (cin_starts_with(s, "typedef")) {
s = cin_skipcomment(s + 7);
@@ -434,7 +407,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 +428,7 @@ static int cin_isinit(void)
return true;
}
- return FALSE;
+ return false;
}
/// Recognize a switch label: "case .*:" or "default:".
@@ -465,7 +438,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;
@@ -499,9 +472,7 @@ bool cin_iscase(const char_u *s, bool strict)
return false;
}
-/*
- * Recognize a "default" switch label.
- */
+// Recognize a "default" switch label.
static int cin_isdefault(const char_u *s)
{
return STRNCMP(s, "default", 7) == 0
@@ -519,7 +490,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);
@@ -580,15 +551,13 @@ static bool cin_is_cpp_namespace(const char_u *s)
return false;
}
-/*
- * Return a pointer to the first non-empty non-comment character after a ':'.
- * Return NULL if not found.
- * case 234: a = b;
- * ^
- */
+// Return a pointer to the first non-empty non-comment character after a ':'.
+// Return NULL if not found.
+// case 234: a = b;
+// ^
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++;
@@ -609,10 +578,8 @@ static const char_u *after_label(const char_u *l)
return l;
}
-/*
- * Get indent of line "lnum", skipping a label.
- * Return 0 if there is nothing after the label.
- */
+// Get indent of line "lnum", skipping a label.
+// Return 0 if there is nothing after the label.
static int get_indent_nolabel(linenr_T lnum) // XXX
{
const char_u *l;
@@ -620,7 +587,7 @@ static int get_indent_nolabel(linenr_T lnum) // XXX
colnr_T col;
const char_u *p;
- l = ml_get(lnum);
+ l = (char_u *)ml_get(lnum);
p = after_label(l);
if (p == NULL) {
return 0;
@@ -632,12 +599,10 @@ static int get_indent_nolabel(linenr_T lnum) // XXX
return (int)col;
}
-/*
- * Find indent for line "lnum", ignoring any case or jump label.
- * Also return a pointer to the text (after the label) in "pp".
- * label: if (asdf && asdfasdf)
- * ^
- */
+// Find indent for line "lnum", ignoring any case or jump label.
+// Also return a pointer to the text (after the label) in "pp".
+// label: if (asdf && asdfasdf)
+// ^
static int skip_label(linenr_T lnum, const char_u **pp)
{
const char_u *l;
@@ -646,17 +611,17 @@ static int skip_label(linenr_T lnum, const char_u **pp)
cursor_save = curwin->w_cursor;
curwin->w_cursor.lnum = lnum;
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
// XXX
if (cin_iscase(l, false) || cin_isscopedecl(l) || cin_islabel()) {
amount = get_indent_nolabel(lnum);
- l = after_label(get_cursor_line_ptr());
+ l = after_label((char_u *)get_cursor_line_ptr());
if (l == NULL) { // just in case
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
}
} else {
amount = get_indent();
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
}
*pp = l;
@@ -664,13 +629,11 @@ static int skip_label(linenr_T lnum, const char_u **pp)
return amount;
}
-/*
- * Return the indent of the first variable name after a type in a declaration.
- * int a, indent of "a"
- * static struct foo b, indent of "b"
- * enum bla c, indent of "c"
- * Returns zero when it doesn't look like a declaration.
- */
+// Return the indent of the first variable name after a type in a declaration.
+// int a, indent of "a"
+// static struct foo b, indent of "b"
+// enum bla c, indent of "c"
+// Returns zero when it doesn't look like a declaration.
static int cin_first_id_amount(void)
{
char_u *line, *p, *s;
@@ -678,12 +641,12 @@ static int cin_first_id_amount(void)
pos_T fp;
colnr_T col;
- line = get_cursor_line_ptr();
+ line = (char_u *)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);
@@ -711,15 +674,13 @@ static int cin_first_id_amount(void)
return (int)col;
}
-/*
- * Return the indent of the first non-blank after an equal sign.
- * char *foo = "here";
- * Return zero if no (useful) equal sign found.
- * Return -1 if the line above "lnum" ends in a backslash.
- * foo = "asdf\
- * asdf\
- * here";
- */
+// Return the indent of the first non-blank after an equal sign.
+// char *foo = "here";
+// Return zero if no (useful) equal sign found.
+// Return -1 if the line above "lnum" ends in a backslash.
+// foo = "asdf{backslash}
+// asdf{backslash}
+// here";
static int cin_get_equal_amount(linenr_T lnum)
{
const char_u *line;
@@ -728,13 +689,14 @@ static int cin_get_equal_amount(linenr_T lnum)
pos_T fp;
if (lnum > 1) {
- line = ml_get(lnum - 1);
+ line = (char_u *)ml_get(lnum - 1);
if (*line != NUL && line[STRLEN(line) - 1] == '\\') {
return -1;
}
}
- line = s = ml_get(lnum);
+ s = (char_u *)ml_get(lnum);
+ line = s;
while (*s != NUL && vim_strchr("=;{}\"'", *s) == NULL) {
if (cin_iscomment(s)) { // ignore comments
s = cin_skipcomment(s);
@@ -761,18 +723,16 @@ static int cin_get_equal_amount(linenr_T lnum)
return (int)col;
}
-/*
- * Recognize a preprocessor statement: Any line that starts with '#'.
- */
+// Recognize a preprocessor statement: Any line that starts with '#'.
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,21 +749,21 @@ 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;
}
if (lnum == 1) {
break;
}
- line = ml_get(--lnum);
+ line = (char_u *)ml_get(--lnum);
if (*line == NUL || line[STRLEN(line) - 1] != '\\') {
break;
}
}
if (lnum != *lnump) {
- *pp = ml_get(*lnump);
+ *pp = (char_u *)ml_get(*lnump);
}
if (retval) {
*amount = candidate_amount;
@@ -811,17 +771,13 @@ static int cin_ispreproc_cont(const char_u **pp, linenr_T *lnump, int *amount)
return retval;
}
-/*
- * Recognize the start of a C or C++ comment.
- */
+// Recognize the start of a C or C++ comment.
static int cin_iscomment(const char_u *p)
{
return p[0] == '/' && (p[1] == '*' || p[1] == '/');
}
-/*
- * Recognize the start of a "//" comment.
- */
+// Recognize the start of a "//" comment.
static int cin_islinecomment(const char_u *p)
{
return p[0] == '/' && p[1] == '/';
@@ -842,7 +798,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);
@@ -899,7 +855,7 @@ static int cin_isfuncdecl(const char_u **sp, linenr_T first_lnum, linenr_T min_l
int just_started = true;
if (sp == NULL) {
- s = ml_get(lnum);
+ s = (char_u *)ml_get(lnum);
} else {
s = *sp;
}
@@ -912,7 +868,7 @@ static int cin_isfuncdecl(const char_u **sp, linenr_T first_lnum, linenr_T min_l
curwin->w_cursor.lnum = save_lnum;
return false;
}
- s = ml_get(lnum);
+ s = (char_u *)ml_get(lnum);
}
curwin->w_cursor.lnum = save_lnum;
@@ -951,7 +907,7 @@ static int cin_isfuncdecl(const char_u **sp, linenr_T first_lnum, linenr_T min_l
// #if defined(x) && {backslash}
// defined(y)
lnum = first_lnum - 1;
- s = ml_get(lnum);
+ s = (char_u *)ml_get(lnum);
if (*s == NUL || s[STRLEN(s) - 1] != '\\') {
retval = true;
}
@@ -960,15 +916,15 @@ static int cin_isfuncdecl(const char_u **sp, linenr_T first_lnum, linenr_T min_l
if ((*s == ',' && cin_nocode(s + 1)) || s[1] == NUL || cin_nocode(s)) {
int comma = (*s == ',');
- /* ',' at the end: continue looking in the next line.
- * At the end: check for ',' in the next line, for this style:
- * func(arg1
- * , arg2) */
+ // ',' at the end: continue looking in the next line.
+ // At the end: check for ',' in the next line, for this style:
+ // func(arg1
+ // , arg2)
for (;;) {
if (lnum >= curbuf->b_ml.ml_line_count) {
break;
}
- s = ml_get(++lnum);
+ s = (char_u *)ml_get(++lnum);
if (!cin_ispreproc(s)) {
break;
}
@@ -993,7 +949,7 @@ static int cin_isfuncdecl(const char_u **sp, linenr_T first_lnum, linenr_T min_l
done:
if (lnum != first_lnum && sp != NULL) {
- *sp = ml_get(first_lnum);
+ *sp = (char_u *)ml_get(first_lnum);
}
return retval;
@@ -1017,11 +973,9 @@ static int cin_isdo(const char_u *p)
return STRNCMP(p, "do", 2) == 0 && !vim_isIDc(p[2]);
}
-/*
- * Check if this is a "while" that should have a matching "do".
- * We only accept a "while (condition) ;", with only white space between the
- * ')' and ';'. The condition may be spread over several lines.
- */
+// Check if this is a "while" that should have a matching "do".
+// We only accept a "while (condition) ;", with only white space between the
+// ')' and ';'. The condition may be spread over several lines.
static int cin_iswhileofdo(const char_u *p, linenr_T lnum) // XXX
{
pos_T cursor_save;
@@ -1036,7 +990,7 @@ static int cin_iswhileofdo(const char_u *p, linenr_T lnum) // XXX
cursor_save = curwin->w_cursor;
curwin->w_cursor.lnum = lnum;
curwin->w_cursor.col = 0;
- p = get_cursor_line_ptr();
+ p = (char_u *)get_cursor_line_ptr();
while (*p && *p != 'w') { // skip any '}', until the 'w' of the "while"
p++;
curwin->w_cursor.col++;
@@ -1050,12 +1004,10 @@ static int cin_iswhileofdo(const char_u *p, linenr_T lnum) // XXX
return retval;
}
-/*
- * Check whether in "p" there is an "if", "for" or "while" before "*poffset".
- * Return 0 if there is none.
- * Otherwise return !0 and update "*poffset" to point to the place where the
- * string was found.
- */
+// Check whether in "p" there is an "if", "for" or "while" before "*poffset".
+// Return 0 if there is none.
+// Otherwise return !0 and update "*poffset" to point to the place where the
+// string was found.
static int cin_is_if_for_while_before_offset(const char_u *line, int *poffset)
{
int offset = *poffset;
@@ -1095,14 +1047,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;
@@ -1115,30 +1065,30 @@ static int cin_iswhileofdo_end(int terminated)
return false;
}
- p = line = get_cursor_line_ptr();
+ p = line = (char_u *)get_cursor_line_ptr();
while (*p != NUL) {
p = cin_skipcomment(p);
if (*p == ')') {
s = (char_u *)skipwhite((char *)p + 1);
if (*s == ';' && cin_nocode(s + 1)) {
- /* Found ");" at end of the line, now check there is "while"
- * before the matching '('. XXX */
+ // Found ");" at end of the line, now check there is "while"
+ // before the matching '('. XXX
i = (int)(p - line);
curwin->w_cursor.col = i;
trypos = find_match_paren(curbuf->b_ind_maxparen);
if (trypos != NULL) {
- s = cin_skipcomment(ml_get(trypos->lnum));
+ s = cin_skipcomment((char_u *)ml_get(trypos->lnum));
if (*s == '}') { // accept "} while (cond);"
s = cin_skipcomment(s + 1);
}
if (cin_starts_with(s, "while")) {
curwin->w_cursor.lnum = trypos->lnum;
- return TRUE;
+ return true;
}
}
// Searching may have made "line" invalid, get it again.
- line = get_cursor_line_ptr();
+ line = (char_u *)get_cursor_line_ptr();
p = line + i;
}
}
@@ -1146,7 +1096,7 @@ static int cin_iswhileofdo_end(int terminated)
p++;
}
}
- return FALSE;
+ return false;
}
static int cin_isbreak(const char_u *p)
@@ -1154,26 +1104,24 @@ static int cin_isbreak(const char_u *p)
return STRNCMP(p, "break", 5) == 0 && !vim_isIDc(p[5]);
}
-/*
- * Find the position of a C++ base-class declaration or
- * constructor-initialization. eg:
- *
- * class MyClass :
- * baseClass <-- here
- * class MyClass : public baseClass,
- * anotherBaseClass <-- here (should probably lineup ??)
- * MyClass::MyClass(...) :
- * baseClass(...) <-- here (constructor-initialization)
- *
- * This is a lot of guessing. Watch out for "cond ? func() : foo".
- */
+// Find the position of a C++ base-class declaration or
+// constructor-initialization. eg:
+//
+// class MyClass :
+// baseClass <-- here
+// class MyClass : public baseClass,
+// anotherBaseClass <-- here (should probably lineup ??)
+// MyClass::MyClass(...) :
+// baseClass(...) <-- here (constructor-initialization)
+//
+// This is a lot of guessing. Watch out for "cond ? func() : foo".
static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached)
{
lpos_T *pos = &cached->lpos; // find position
const char_u *s;
int class_or_struct, lookfor_ctor_init, cpp_base_class;
linenr_T lnum = curwin->w_cursor.lnum;
- const char_u *line = get_cursor_line_ptr();
+ const char_u *line = (char_u *)get_cursor_line_ptr();
if (pos->lnum <= lnum) {
return cached->found; // Use the cached result
@@ -1190,23 +1138,22 @@ static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached)
return 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:
- * a = cond ?
- * func() :
- * asdf;
- * func::foo()
- * : something
- * {}
- * Foo::Foo (int one, int two)
- * : something(4),
- * somethingelse(3)
- * {}
- */
+ 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:
+ // a = cond ?
+ // func() :
+ // asdf;
+ // func::foo()
+ // : something
+ // {}
+ // Foo::Foo (int one, int two)
+ // : something(4),
+ // somethingelse(3)
+ // {}
while (lnum > 1) {
- line = ml_get(lnum - 1);
+ line = (char_u *)ml_get(lnum - 1);
s = (char_u *)skipwhite((char *)line);
if (*s == '#' || *s == NUL) {
break;
@@ -1228,7 +1175,7 @@ static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached)
}
pos->lnum = lnum;
- line = ml_get(lnum);
+ line = (char_u *)ml_get(lnum);
s = line;
for (;;) {
if (*s == NUL) {
@@ -1236,7 +1183,7 @@ static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached)
break;
}
// Continue in the cursor line.
- line = ml_get(++lnum);
+ line = (char_u *)ml_get(++lnum);
s = line;
}
if (s == line) {
@@ -1254,13 +1201,13 @@ static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached)
s = skip_string(s) + 1;
} else if (s[0] == ':') {
if (s[1] == ':') {
- /* skip double colon. It can't be a constructor
- * initialization any more */
- lookfor_ctor_init = FALSE;
+ // skip double colon. It can't be a constructor
+ // initialization any more
+ 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
- * cpp-base-class-declaration or constructor-initialization */
+ // we have something found, that looks like the start of
+ // cpp-base-class-declaration or constructor-initialization
cpp_base_class = true;
lookfor_ctor_init = class_or_struct = false;
pos->col = 0;
@@ -1270,8 +1217,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 +1227,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;
+ // Constructor-initialization is assumed if we come across
+ // something like "):"
+ class_or_struct = false;
+ lookfor_ctor_init = true;
} else if (s[0] == '?') {
// Avoid seeing '() :' after '?' as constructor init.
return false;
@@ -1327,11 +1274,11 @@ static int get_baseclass_amount(int col)
if (col == 0) {
amount = get_indent();
- if (find_last_paren(get_cursor_line_ptr(), '(', ')')
+ if (find_last_paren((char_u *)get_cursor_line_ptr(), '(', ')')
&& (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL) {
amount = get_indent_lnum(trypos->lnum); // XXX
}
- if (!cin_ends_in(get_cursor_line_ptr(), (char_u *)",", NULL)) {
+ if (!cin_ends_in((char_u *)get_cursor_line_ptr(), (char_u *)",", NULL)) {
amount += curbuf->b_ind_cpp_baseclass;
}
} else {
@@ -1345,11 +1292,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 +1316,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);
@@ -1420,17 +1363,16 @@ static int cin_is_cpp_extern_c(const char_u *s)
return false;
}
-/*
- * Skip strings, chars and comments until at or past "trypos".
- * Return the column found.
- */
+// Skip strings, chars and comments until at or past "trypos".
+// Return the column found.
static int cin_skip2pos(pos_T *trypos)
{
const char_u *line;
const char_u *p;
const char_u *new_p;
- p = line = ml_get(trypos->lnum);
+ line = (char_u *)ml_get(trypos->lnum);
+ p = line;
while (*p && (colnr_T)(p - line) < trypos->col) {
if (cin_iscomment(p)) {
p = cin_skipcomment(p);
@@ -1446,11 +1388,10 @@ static int cin_skip2pos(pos_T *trypos)
return (int)(p - line);
}
-/*
- * Find the '{' at the start of the block we are in.
- * Return NULL if no match found.
- * Ignore a '{' that is in a comment, makes indenting the next three lines
- * work. */
+// Find the '{' at the start of the block we are in.
+// Return NULL if no match found.
+// Ignore a '{' that is in a comment, makes indenting the next three lines
+// work.
// foo()
// {
// }
@@ -1550,12 +1491,10 @@ static pos_T *find_match_paren_after_brace(int ind_maxparen)
return trypos;
}
-/*
- * Return ind_maxparen corrected for the difference in line number between the
- * cursor position and "startpos". This makes sure that searching for a
- * matching paren above the cursor line doesn't find a match because of
- * looking a few lines further.
- */
+// Return ind_maxparen corrected for the difference in line number between the
+// cursor position and "startpos". This makes sure that searching for a
+// matching paren above the cursor line doesn't find a match because of
+// looking a few lines further.
static int corr_ind_maxparen(pos_T *startpos)
{
long n = (long)startpos->lnum - (long)curwin->w_cursor.lnum;
@@ -1566,14 +1505,12 @@ static int corr_ind_maxparen(pos_T *startpos)
return curbuf->b_ind_maxparen;
}
-/*
- * Set w_cursor.col to the column number of the last unmatched ')' or '{' in
- * line "l". "l" must point to the start of the line.
- */
+// Set w_cursor.col to the column number of the last unmatched ')' or '{' in
+// line "l". "l" must point to the start of the line.
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,17 +1525,15 @@ 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;
}
}
}
return retval;
}
-/*
- * Parse 'cinoptions' and set the values in "curbuf".
- * Must be called when 'cinoptions', 'shiftwidth' and/or 'tabstop' changes.
- */
+// Parse 'cinoptions' and set the values in "curbuf".
+// Must be called when 'cinoptions', 'shiftwidth' and/or 'tabstop' changes.
void parse_cino(buf_T *buf)
{
char *p;
@@ -1607,39 +1542,37 @@ void parse_cino(buf_T *buf)
int fraction = 0;
int sw = get_sw_value(buf);
- /*
- * Set the default values.
- */
- /* Spaces from a block's opening brace the prevailing indent for that
- * block should be. */
+ // Set the default values.
+ // Spaces from a block's opening brace the prevailing indent for that
+ // block should be.
buf->b_ind_level = sw;
- /* Spaces from the edge of the line an open brace that's at the end of a
- * line is imagined to be. */
+ // Spaces from the edge of the line an open brace that's at the end of a
+ // line is imagined to be.
buf->b_ind_open_imag = 0;
- /* Spaces from the prevailing indent for a line that is not preceded by
- * an opening brace. */
+ // Spaces from the prevailing indent for a line that is not preceded by
+ // an opening brace.
buf->b_ind_no_brace = 0;
// Column where the first { of a function should be located }.
buf->b_ind_first_open = 0;
- /* Spaces from the prevailing indent a leftmost open brace should be
- * located. */
+ // Spaces from the prevailing indent a leftmost open brace should be
+ // located.
buf->b_ind_open_extra = 0;
- /* Spaces from the matching open brace (real location for one at the left
- * edge; imaginary location from one that ends a line) the matching close
- * brace should be located. */
+ // Spaces from the matching open brace (real location for one at the left
+ // edge; imaginary location from one that ends a line) the matching close
+ // brace should be located.
buf->b_ind_close_extra = 0;
- /* Spaces from the edge of the line an open brace sitting in the leftmost
- * column is imagined to be. */
+ // Spaces from the edge of the line an open brace sitting in the leftmost
+ // column is imagined to be.
buf->b_ind_open_left_imag = 0;
- /* Spaces jump labels should be shifted to the left if N is non-negative,
- * otherwise the jump label will be put to column 1. */
+ // Spaces jump labels should be shifted to the left if N is non-negative,
+ // otherwise the jump label will be put to column 1.
buf->b_ind_jump_label = -1;
// Spaces from the switch() indent a "case xx" label should be located.
@@ -1651,8 +1584,8 @@ void parse_cino(buf_T *buf)
// Lineup break at end of case in switch() with case label.
buf->b_ind_case_break = 0;
- /* Spaces from the class declaration indent a scope declaration label
- * should be located. */
+ // Spaces from the class declaration indent a scope declaration label
+ // should be located.
buf->b_ind_scopedecl = sw;
// Spaces from the scope declaration label code should be located.
@@ -1664,32 +1597,32 @@ void parse_cino(buf_T *buf)
// Amount a function type spec should be indented.
buf->b_ind_func_type = sw;
- /* Amount a cpp base class declaration or constructor initialization
- * should be indented. */
+ // Amount a cpp base class declaration or constructor initialization
+ // should be indented.
buf->b_ind_cpp_baseclass = sw;
- /* additional spaces beyond the prevailing indent a continuation line
- * should be located. */
+ // additional spaces beyond the prevailing indent a continuation line
+ // should be located.
buf->b_ind_continuation = sw;
// Spaces from the indent of the line with an unclosed parentheses.
buf->b_ind_unclosed = sw * 2;
- /* Spaces from the indent of the line with an unclosed parentheses, which
- * itself is also unclosed. */
+ // Spaces from the indent of the line with an unclosed parentheses, which
+ // itself is also unclosed.
buf->b_ind_unclosed2 = sw;
// Suppress ignoring spaces from the indent of a line starting with an
// unclosed parenthesis.
buf->b_ind_unclosed_noignore = 0;
- /* If the opening paren is the last nonwhite character on the line, and
- * b_ind_unclosed_wrapped is nonzero, use this indent relative to the outer
- * context (for very long lines). */
+ // If the opening paren is the last nonwhite character on the line, and
+ // b_ind_unclosed_wrapped is nonzero, use this indent relative to the outer
+ // context (for very long lines).
buf->b_ind_unclosed_wrapped = 0;
- /* Suppress ignoring white space when lining up with the character after
- * an unclosed parentheses. */
+ // Suppress ignoring white space when lining up with the character after
+ // an unclosed parentheses.
buf->b_ind_unclosed_whiteok = 0;
// Indent a closing parenthesis under the line start of the matching
@@ -1705,8 +1638,8 @@ void parse_cino(buf_T *buf)
// Spaces from the comment opener when there is nothing after it.
buf->b_ind_in_comment = 3;
- /* Boolean: if non-zero, use b_ind_in_comment even if there is something
- * after the comment opener. */
+ // Boolean: if non-zero, use b_ind_in_comment even if there is something
+ // after the comment opener.
buf->b_ind_in_comment2 = 0;
// Max lines to search for an open paren.
@@ -1727,8 +1660,8 @@ void parse_cino(buf_T *buf)
// Handle C++ namespace.
buf->b_ind_cpp_namespace = 0;
- /* Handle continuation lines containing conditions of if(), for() and
- * while(). */
+ // Handle continuation lines containing conditions of if(), for() and
+ // while().
buf->b_ind_if_for_while = 0;
// indentation for # comments
@@ -1740,7 +1673,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++;
@@ -1774,8 +1707,8 @@ void parse_cino(buf_T *buf)
n = -n;
}
- /* When adding an entry here, also update the default 'cinoptions' in
- * doc/indent.txt, and add explanation for it! */
+ // When adding an entry here, also update the default 'cinoptions' in
+ // doc/indent.txt, and add explanation for it!
switch (*l) {
case '>':
buf->b_ind_level = n;
@@ -1895,10 +1828,8 @@ void parse_cino(buf_T *buf)
}
}
-/*
- * Return the desired indent for C code.
- * Return -1 if the indent should be left alone (inside a raw string).
- */
+// Return the desired indent for C code.
+// Return -1 if the indent should be left alone (inside a raw string).
int get_c_indent(void)
{
pos_T cur_curpos;
@@ -1907,7 +1838,7 @@ int get_c_indent(void)
int cur_amount = MAXCOL;
colnr_T col;
char_u *theline;
- char_u *linecopy;
+ char *linecopy;
pos_T *trypos;
pos_T *comment_pos;
pos_T *tryposBrace = NULL;
@@ -1959,25 +1890,23 @@ int get_c_indent(void)
return 0;
}
- /* Get a copy of the current contents of the line.
- * This is required, because only the most recent line obtained with
- * ml_get is valid! */
- linecopy = vim_strsave(ml_get(cur_curpos.lnum));
+ // Get a copy of the current contents of the line.
+ // This is required, because only the most recent line obtained with
+ // ml_get is valid!
+ linecopy = xstrdup(ml_get(cur_curpos.lnum));
- /*
- * In insert mode and the cursor is on a ')' truncate the line at the
- * cursor position. We don't want to line up with the matching '(' when
- * inserting new stuff.
- * For unknown reasons the cursor might be past the end of the line, thus
- * check for that.
- */
+ // In insert mode and the cursor is on a ')' truncate the line at the
+ // cursor position. We don't want to line up with the matching '(' when
+ // inserting new stuff.
+ // For unknown reasons the cursor might be past the end of the line, thus
+ // check for that.
if ((State & MODE_INSERT)
&& curwin->w_cursor.col < (colnr_T)STRLEN(linecopy)
&& linecopy[curwin->w_cursor.col] == ')') {
linecopy[curwin->w_cursor.col] = NUL;
}
- theline = (char_u *)skipwhite((char *)linecopy);
+ theline = (char_u *)skipwhite(linecopy);
// move the cursor to the start of the line
@@ -1985,10 +1914,8 @@ int get_c_indent(void)
original_line_islabel = cin_islabel(); // XXX
- /*
- * If we are inside a raw string don't change the indent.
- * Ignore a raw string inside a comment.
- */
+ // If we are inside a raw string don't change the indent.
+ // Ignore a raw string inside a comment.
comment_pos = ind_find_start_comment();
if (comment_pos != NULL) {
// findmatchlimit() static pos is overwritten, make a copy
@@ -2018,10 +1945,8 @@ int get_c_indent(void)
amount = 0;
goto theend;
}
- /*
- * If we're inside a "//" comment and there is a "//" comment in a
- * previous line, lineup with that one.
- */
+ // If we're inside a "//" comment and there is a "//" comment in a
+ // previous line, lineup with that one.
if (cin_islinecomment(theline)) {
pos_T linecomment_pos;
@@ -2042,10 +1967,8 @@ int get_c_indent(void)
goto theend;
}
}
- /*
- * If we're inside a comment and not looking at the start of the
- * comment, try using the 'comments' option.
- */
+ // If we're inside a comment and not looking at the start of the
+ // comment, try using the 'comments' option.
if (!cin_iscomment(theline) && comment_pos != NULL) { // XXX
int lead_start_len = 2;
int lead_middle_len = 1;
@@ -2055,7 +1978,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 +1986,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;
@@ -2094,17 +2017,17 @@ int get_c_indent(void)
STRCPY(lead_middle, lead_end);
lead_middle_len = (int)STRLEN(lead_middle);
} else if (what == COM_END) {
- /* If our line starts with the middle comment string, line it
- * up with the comment opener per the 'comments' option. */
+ // If our line starts with the middle comment string, line it
+ // 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
- * the middle comment string matches in the previous
- * line, use the indent of that line. XXX */
- look = (char_u *)skipwhite((char *)ml_get(curwin->w_cursor.lnum - 1));
+ // If the start comment string matches in the previous
+ // line, use the indent of that line plus offset. If
+ // the middle comment string matches in the previous
+ // line, use the indent of that line. XXX
+ look = (char_u *)skipwhite(ml_get(curwin->w_cursor.lnum - 1));
if (STRNCMP(look, lead_start, lead_start_len) == 0) {
amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
} else if (STRNCMP(look, lead_middle, lead_middle_len) == 0) {
@@ -2125,8 +2048,8 @@ int get_c_indent(void)
break;
}
- /* If our line starts with the end comment string, line it up
- * with the middle comment */
+ // If our line starts with the end comment string, line it up
+ // with the middle comment
if (STRNCMP(theline, lead_middle, lead_middle_len) != 0
&& STRNCMP(theline, lead_end, STRLEN(lead_end)) == 0) {
amount = get_indent_lnum(curwin->w_cursor.lnum - 1);
@@ -2142,10 +2065,9 @@ int get_c_indent(void)
}
}
- /* If our line starts with an asterisk, line up with the
- * asterisk in the comment opener; otherwise, line up
- * with the first character of the comment text.
- */
+ // If our line starts with an asterisk, line up with the
+ // asterisk in the comment opener; otherwise, line up
+ // with the first character of the comment text.
if (done) {
// skip
} else if (theline[0] == '*') {
@@ -2166,7 +2088,7 @@ int get_c_indent(void)
}
if (amount == -1) { // use the comment opener
if (!curbuf->b_ind_in_comment2) {
- start = ml_get(comment_pos->lnum);
+ start = (char_u *)ml_get(comment_pos->lnum);
look = start + comment_pos->col + 2; // skip / and *
if (*look != NUL) { // if something after it
comment_pos->col = (colnr_T)((char_u *)skipwhite((char *)look) - start);
@@ -2195,8 +2117,8 @@ int get_c_indent(void)
|| (tryposBrace = find_start_brace()) != NULL
|| trypos != NULL) {
if (trypos != NULL && tryposBrace != NULL) {
- /* Both an unmatched '(' and '{' is found. Use the one which is
- * closer to the current cursor position, set the other to NULL. */
+ // Both an unmatched '(' and '{' is found. Use the one which is
+ // closer to the current cursor position, set the other to NULL.
if (trypos->lnum != tryposBrace->lnum
? trypos->lnum < tryposBrace->lnum
: trypos->col < tryposBrace->col) {
@@ -2208,17 +2130,15 @@ int get_c_indent(void)
if (trypos != NULL) {
our_paren_pos = *trypos;
- /*
- * If the matching paren is more than one line away, use the indent of
- * a previous non-empty line that matches the same paren.
- */
+ // If the matching paren is more than one line away, use the indent of
+ // a previous non-empty line that matches the same paren.
if (theline[0] == ')' && curbuf->b_ind_paren_prev) {
// Line up with the start of the matching paren line.
amount = get_indent_lnum(curwin->w_cursor.lnum - 1); // XXX
} else {
amount = -1;
for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; lnum--) {
- l = (char_u *)skipwhite((char *)ml_get(lnum));
+ l = (char_u *)skipwhite(ml_get(lnum));
if (cin_nocode(l)) { // skip comment lines
continue;
}
@@ -2251,18 +2171,16 @@ int get_c_indent(void)
}
}
- /*
- * Line up with line where the matching paren is. XXX
- * If the line starts with a '(' or the indent for unclosed
- * parentheses is zero, line up with the unclosed parentheses.
- */
+ // Line up with line where the matching paren is. XXX
+ // If the line starts with a '(' or the indent for unclosed
+ // parentheses is zero, line up with the unclosed parentheses.
if (amount == -1) {
int ignore_paren_col = 0;
int is_if_for_while = 0;
if (curbuf->b_ind_if_for_while) {
- /* Look for the outermost opening parenthesis on this line
- * and check whether it belongs to an "if", "for" or "while". */
+ // Look for the outermost opening parenthesis on this line
+ // and check whether it belongs to an "if", "for" or "while".
pos_T cursor_save = curwin->w_cursor;
pos_T outermost;
@@ -2279,7 +2197,7 @@ int get_c_indent(void)
curwin->w_cursor = cursor_save;
- line = ml_get(outermost.lnum);
+ line = (char_u *)ml_get(outermost.lnum);
is_if_for_while =
cin_is_if_for_while_before_offset(line, &outermost.col);
@@ -2292,10 +2210,10 @@ int get_c_indent(void)
char_u *line;
int look_col;
- /* Ignore a '(' in front of the line that has a match before
- * our matching '('. */
+ // Ignore a '(' in front of the line that has a match before
+ // our matching '('.
curwin->w_cursor.lnum = our_paren_pos.lnum;
- line = get_cursor_line_ptr();
+ line = (char_u *)get_cursor_line_ptr();
look_col = (int)(look - line);
curwin->w_cursor.col = look_col + 1;
if ((trypos = findmatchlimit(NULL, ')', 0,
@@ -2307,30 +2225,28 @@ int get_c_indent(void)
}
curwin->w_cursor.lnum = save_lnum;
- look = ml_get(our_paren_pos.lnum) + look_col;
+ look = (char_u *)ml_get(our_paren_pos.lnum) + look_col;
}
if (theline[0] == ')' || (curbuf->b_ind_unclosed == 0
&& is_if_for_while == 0)
|| (!curbuf->b_ind_unclosed_noignore && *look == '('
&& ignore_paren_col == 0)) {
- /*
- * If we're looking at a close paren, line up right there;
- * otherwise, line up with the next (non-white) character.
- * When b_ind_unclosed_wrapped is set and the matching paren is
- * the last nonwhite character of the line, use either the
- * indent of the current line or the indentation of the next
- * outer paren and add b_ind_unclosed_wrapped (for very long
- * lines).
- */
+ // If we're looking at a close paren, line up right there;
+ // otherwise, line up with the next (non-white) character.
+ // When b_ind_unclosed_wrapped is set and the matching paren is
+ // the last nonwhite character of the line, use either the
+ // indent of the current line or the indentation of the next
+ // outer paren and add b_ind_unclosed_wrapped (for very long
+ // lines).
if (theline[0] != ')') {
cur_amount = MAXCOL;
- l = ml_get(our_paren_pos.lnum);
+ l = (char_u *)ml_get(our_paren_pos.lnum);
if (curbuf->b_ind_unclosed_wrapped
&& cin_ends_in(l, (char_u *)"(", NULL)) {
- /* look for opening unmatched paren, indent one level
- * for each additional level */
+ // 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 '{':
@@ -2363,10 +2279,8 @@ int get_c_indent(void)
}
}
- /*
- * Find how indented the paren is, or the character after it
- * if we did the above "if".
- */
+ // Find how indented the paren is, or the character after it
+ // if we did the above "if".
if (our_paren_pos.col > 0) {
getvcol(curwin, &our_paren_pos, &col, NULL, NULL);
if (cur_amount > (int)col) {
@@ -2384,11 +2298,11 @@ int get_c_indent(void)
amount = cur_amount;
}
} else {
- /* Add b_ind_unclosed2 for each '(' before our matching one,
- * but ignore (void) before the line (ignore_paren_col). */
+ // Add b_ind_unclosed2 for each '(' before our matching one,
+ // 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;
@@ -2401,8 +2315,8 @@ int get_c_indent(void)
}
}
- /* Use b_ind_unclosed once, when the first '(' is not inside
- * braces */
+ // Use b_ind_unclosed once, when the first '(' is not inside
+ // braces
if (col == MAXCOL) {
amount += curbuf->b_ind_unclosed;
} else {
@@ -2418,14 +2332,12 @@ int get_c_indent(void)
}
}
}
- /*
- * For a line starting with ')' use the minimum of the two
- * positions, to avoid giving it more indent than the previous
- * lines:
- * func_long_name( if (x
- * arg && yy
- * ) ^ not here ) ^ not here
- */
+ // For a line starting with ')' use the minimum of the two
+ // positions, to avoid giving it more indent than the previous
+ // lines:
+ // func_long_name( if (x
+ // arg && yy
+ // ) ^ not here ) ^ not here
if (cur_amount < amount) {
amount = cur_amount;
}
@@ -2445,14 +2357,12 @@ int get_c_indent(void)
tryposBrace = &tryposCopy;
trypos = tryposBrace;
ourscope = trypos->lnum;
- start = ml_get(ourscope);
-
- /*
- * Now figure out how indented the line is in general.
- * If the brace was at the start of the line, we use that;
- * otherwise, check out the indentation of the line as
- * a whole and then add the "imaginary indent" to that.
- */
+ start = (char_u *)ml_get(ourscope);
+
+ // Now figure out how indented the line is in general.
+ // If the brace was at the start of the line, we use that;
+ // otherwise, check out the indentation of the line as
+ // a whole and then add the "imaginary indent" to that.
look = (char_u *)skipwhite((char *)start);
if (*look == '{') {
getvcol(curwin, trypos, &col, NULL, NULL);
@@ -2480,7 +2390,7 @@ int get_c_indent(void)
// ldfd) {
// }
if ((curbuf->b_ind_js || curbuf->b_ind_keep_case_label)
- && cin_iscase((char_u *)skipwhite((char *)get_cursor_line_ptr()), false)) {
+ && cin_iscase((char_u *)skipwhite(get_cursor_line_ptr()), false)) {
amount = get_indent();
} else if (curbuf->b_ind_js) {
amount = get_indent_lnum(lnum);
@@ -2498,18 +2408,14 @@ int get_c_indent(void)
// we want to be. Otherwise, add the amount of room
// that an indent is supposed to be.
if (theline[0] == '}') {
- /*
- * they may want closing braces to line up with something
- * other than the open brace. indulge them, if so.
- */
+ // they may want closing braces to line up with something
+ // other than the open brace. indulge them, if so.
amount += curbuf->b_ind_close_extra;
} else {
- /*
- * If we're looking at an "else", try to find an "if"
- * to match it with.
- * If we're looking at a "while", try to find a "do"
- * to match it with.
- */
+ // If we're looking at an "else", try to find an "if"
+ // to match it with.
+ // If we're looking at a "while", try to find a "do"
+ // to match it with.
lookfor = LOOKFOR_INITIAL;
if (cin_iselse(theline)) {
lookfor = LOOKFOR_IF;
@@ -2524,18 +2430,14 @@ int get_c_indent(void)
}
}
- /*
- * We get here if we are not on an "while-of-do" or "else" (or
- * failed to find a matching "if").
- * Search backwards for something to line up with.
- * First set amount for when we don't find anything.
- */
+ // We get here if we are not on an "while-of-do" or "else" (or
+ // failed to find a matching "if").
+ // Search backwards for something to line up with.
+ // First set amount for when we don't find anything.
- /*
- * if the '{' is _really_ at the left margin, use the imaginary
- * location of a left-margin brace. Otherwise, correct the
- * location for b_ind_open_extra.
- */
+ // if the '{' is _really_ at the left margin, use the imaginary
+ // location of a left-margin brace. Otherwise, correct the
+ // location for b_ind_open_extra.
if (start_brace == BRACE_IN_COL0) { // '{' is in column 0
amount = curbuf->b_ind_open_left_imag;
@@ -2547,7 +2449,7 @@ int get_c_indent(void)
if (start_brace == BRACE_AT_END) { // '{' is at end of line
amount += curbuf->b_ind_open_imag;
- l = (char_u *)skipwhite((char *)get_cursor_line_ptr());
+ l = (char_u *)skipwhite(get_cursor_line_ptr());
if (cin_is_cpp_namespace(l)) {
amount += curbuf->b_ind_cpp_namespace;
} else if (cin_is_cpp_extern_c(l)) {
@@ -2562,7 +2464,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
@@ -2594,10 +2496,8 @@ int get_c_indent(void)
curwin->w_cursor.lnum--;
curwin->w_cursor.col = 0;
- /*
- * If we went all the way back to the start of our scope, line
- * up with it.
- */
+ // If we went all the way back to the start of our scope, line
+ // up with it.
if (curwin->w_cursor.lnum <= ourscope) {
// We reached end of scope:
// If looking for a enum or structure initialization
@@ -2611,9 +2511,9 @@ int get_c_indent(void)
if (curwin->w_cursor.lnum == 0
|| curwin->w_cursor.lnum
< ourscope - curbuf->b_ind_maxparen) {
- /* nothing found (abuse curbuf->b_ind_maxparen as
- * limit) assume terminated line (i.e. a variable
- * initialization) */
+ // nothing found (abuse curbuf->b_ind_maxparen as
+ // limit) assume terminated line (i.e. a variable
+ // initialization)
if (cont_amount > 0) {
amount = cont_amount;
} else if (!curbuf->b_ind_js) {
@@ -2622,12 +2522,10 @@ int get_c_indent(void)
break;
}
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
- /*
- * If we're in a comment or raw string now, skip to
- * the start of it.
- */
+ // If we're in a comment or raw string now, skip to
+ // the start of it.
trypos = ind_find_start_CORS(NULL);
if (trypos != NULL) {
curwin->w_cursor.lnum = trypos->lnum + 1;
@@ -2646,29 +2544,25 @@ 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
- * function declaration, we are done
- * (it's a variable declaration).
- */
+ // If we are at top level and the line looks like a
+ // function declaration, we are done
+ // (it's a variable declaration).
if (start_brace != BRACE_IN_COL0
|| !cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0)) {
- /* if the line is terminated with another ','
- * it is a continued variable initialization.
- * don't add extra indent.
- * TODO: does not work, if a function
- * declaration is split over multiple lines:
- * cin_isfuncdecl returns FALSE then.
- */
+ // if the line is terminated with another ','
+ // it is a continued variable initialization.
+ // don't add extra indent.
+ // TODO(vim): does not work, if a function
+ // declaration is split over multiple lines:
+ // cin_isfuncdecl returns false then.
if (terminated == ',') {
break;
}
- /* if it is an enum declaration or an assignment,
- * we are done.
- */
+ // if it is an enum declaration or an assignment,
+ // we are done.
if (terminated != ';' && cin_isinit()) {
break;
}
@@ -2700,11 +2594,10 @@ int get_c_indent(void)
}
}
- /* it's a variable declaration, add indentation
- * like in
- * int a,
- * b;
- */
+ // it's a variable declaration, add indentation
+ // like in
+ // int a,
+ // b;
if (cont_amount > 0) {
amount = cont_amount;
} else {
@@ -2728,10 +2621,8 @@ int get_c_indent(void)
}
if (lookfor_cpp_namespace) {
- /*
- * Looking for C++ namespace, need to look further
- * back.
- */
+ // Looking for C++ namespace, need to look further
+ // back.
if (curwin->w_cursor.lnum == ourscope) {
continue;
}
@@ -2742,10 +2633,10 @@ int get_c_indent(void)
break;
}
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
- /* If we're in a comment or raw string now, skip
- * to the start of it. */
+ // If we're in a comment or raw string now, skip
+ // to the start of it.
trypos = ind_find_start_CORS(NULL);
if (trypos != NULL) {
curwin->w_cursor.lnum = trypos->lnum + 1;
@@ -2785,22 +2676,20 @@ int get_c_indent(void)
continue;
}
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
- /*
- * If this is a switch() label, may line up relative to that.
- * If this is a C++ scope declaration, do the same.
- */
+ // If this is a switch() label, may line up relative to that.
+ // If this is a C++ scope declaration, do the same.
bool iscase = cin_iscase(l, false);
if (iscase || cin_isscopedecl(l)) {
- /* we are only looking for cpp base class
- * declaration/initialization any longer */
+ // we are only looking for cpp base class
+ // declaration/initialization any longer
if (lookfor == LOOKFOR_CPP_BASECLASS) {
break;
}
- /* When looking for a "do" we are not interested in
- * labels. */
+ // When looking for a "do" we are not interested in
+ // labels.
if (whilelevel > 0) {
continue;
}
@@ -2861,8 +2750,8 @@ int get_c_indent(void)
// -> y = y + 1;
if (n) {
amount = n;
- l = after_label(get_cursor_line_ptr());
- if (l != NULL && cin_is_cinword(l)) {
+ l = after_label((char_u *)get_cursor_line_ptr());
+ if (l != NULL && cin_is_cinword((char *)l)) {
if (theline[0] == '{') {
amount += curbuf->b_ind_open_extra;
} else {
@@ -2873,14 +2762,12 @@ int get_c_indent(void)
break;
}
- /*
- * Try to get the indent of a statement before the switch
- * label. If nothing is found, line up relative to the
- * switch label.
- * break; <- may line up with this line
- * case xx:
- * -> y = 1;
- */
+ // Try to get the indent of a statement before the switch
+ // label. If nothing is found, line up relative to the
+ // switch label.
+ // break; <- may line up with this line
+ // case xx:
+ // -> y = 1;
scope_amount = get_indent() + (iscase // XXX
? curbuf->b_ind_case_code
: curbuf->b_ind_scopedecl_code);
@@ -2889,10 +2776,8 @@ int get_c_indent(void)
continue;
}
- /*
- * Looking for a switch() label or C++ scope declaration,
- * ignore other lines, skip {}-blocks.
- */
+ // Looking for a switch() label or C++ scope declaration,
+ // ignore other lines, skip {}-blocks.
if (lookfor == LOOKFOR_CASE || lookfor == LOOKFOR_SCOPEDECL) {
if (find_last_paren(l, '{', '}')
&& (trypos = find_start_brace()) != NULL) {
@@ -2902,23 +2787,19 @@ int get_c_indent(void)
continue;
}
- /*
- * Ignore jump labels with nothing after them.
- */
+ // Ignore jump labels with nothing after them.
if (!curbuf->b_ind_js && cin_islabel()) {
- l = after_label(get_cursor_line_ptr());
+ l = after_label((char_u *)get_cursor_line_ptr());
if (l == NULL || cin_nocode(l)) {
continue;
}
}
- /*
- * Ignore #defines, #if, etc.
- * Ignore comment and empty lines.
- * (need to get the line again, cin_islabel() may have
- * unlocked it)
- */
- l = get_cursor_line_ptr();
+ // Ignore #defines, #if, etc.
+ // Ignore comment and empty lines.
+ // (need to get the line again, cin_islabel() may have
+ // unlocked it)
+ l = (char_u *)get_cursor_line_ptr();
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)
|| cin_nocode(l)) {
continue;
@@ -2930,7 +2811,7 @@ int get_c_indent(void)
n = 0;
if (lookfor != LOOKFOR_TERM && curbuf->b_ind_cpp_baseclass > 0) {
n = cin_is_cpp_baseclass(&cache_cpp_baseclass);
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
}
if (n) {
if (lookfor == LOOKFOR_UNTERM) {
@@ -2950,9 +2831,8 @@ int get_c_indent(void)
}
break;
} else if (lookfor == LOOKFOR_CPP_BASECLASS) {
- /* only look, whether there is a cpp base class
- * declaration or initialization before the opening brace.
- */
+ // only look, whether there is a cpp base class
+ // declaration or initialization before the opening brace.
if (cin_isterminated(l, true, false)) {
break;
} else {
@@ -2960,18 +2840,16 @@ int get_c_indent(void)
}
}
- /*
- * What happens next depends on the line being terminated.
- * If terminated with a ',' only consider it terminating if
- * there is another unterminated statement behind, eg:
- * 123,
- * sizeof
- * here
- * Otherwise check whether it is an enumeration or structure
- * initialisation (not indented) or a variable declaration
- * (indented).
- */
- terminated = cin_isterminated(l, FALSE, TRUE);
+ // What happens next depends on the line being terminated.
+ // If terminated with a ',' only consider it terminating if
+ // there is another unterminated statement behind, eg:
+ // 123,
+ // sizeof
+ // here
+ // Otherwise check whether it is an enumeration or structure
+ // initialisation (not indented) or a variable declaration
+ // (indented).
+ terminated = cin_isterminated(l, false, true);
if (js_cur_has_key) {
js_cur_has_key = false; // only check the first line
@@ -3040,14 +2918,12 @@ int get_c_indent(void)
}
if (trypos != NULL) {
- /*
- * Check if we are on a case label now. This is
- * handled above.
- * case xx: if ( asdf &&
- * asdf)
- */
+ // Check if we are on a case label now. This is
+ // handled above.
+ // case xx: if ( asdf &&
+ // asdf)
curwin->w_cursor = *trypos;
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
if (cin_iscase(l, false) || cin_isscopedecl(l)) {
curwin->w_cursor.lnum++;
curwin->w_cursor.col = 0;
@@ -3055,16 +2931,14 @@ int get_c_indent(void)
}
}
- /*
- * Skip over continuation lines to find the one to get the
- * indent from
- * char *usethis = "bla\
- * bla",
- * here;
- */
+ // Skip over continuation lines to find the one to get the
+ // indent from
+ // char *usethis = "bla{backslash}
+ // bla",
+ // here;
if (terminated == ',') {
while (curwin->w_cursor.lnum > 1) {
- l = ml_get(curwin->w_cursor.lnum - 1);
+ l = (char_u *)ml_get(curwin->w_cursor.lnum - 1);
if (*l == NUL || l[STRLEN(l) - 1] != '\\') {
break;
}
@@ -3073,50 +2947,42 @@ int get_c_indent(void)
}
}
- /*
- * Get indent and pointer to text for current line,
- * ignoring any jump label. XXX
- */
+ // Get indent and pointer to text for current line,
+ // ignoring any jump label. XXX
if (curbuf->b_ind_js) {
cur_amount = get_indent();
} else {
cur_amount = skip_label(curwin->w_cursor.lnum, &l);
}
- /*
- * If this is just above the line we are indenting, and it
- * starts with a '{', line it up with this line.
- * while (not)
- * -> {
- * }
- */
+ // If this is just above the line we are indenting, and it
+ // starts with a '{', line it up with this line.
+ // while (not)
+ // -> {
+ // }
if (terminated != ',' && lookfor != LOOKFOR_TERM
&& theline[0] == '{') {
amount = cur_amount;
- /*
- * Only add b_ind_open_extra when the current line
- * doesn't start with a '{', which must have a match
- * in the same line (scope is the same). Probably:
- * { 1, 2 },
- * -> { 3, 4 }
- */
+ // Only add b_ind_open_extra when the current line
+ // doesn't start with a '{', which must have a match
+ // in the same line (scope is the same). Probably:
+ // { 1, 2 },
+ // -> { 3, 4 }
if (*skipwhite((char *)l) != '{') {
amount += curbuf->b_ind_open_extra;
}
if (curbuf->b_ind_cpp_baseclass && !curbuf->b_ind_js) {
- /* have to look back, whether it is a cpp base
- * class declaration or initialization */
+ // have to look back, whether it is a cpp base
+ // class declaration or initialization
lookfor = LOOKFOR_CPP_BASECLASS;
continue;
}
break;
}
- /*
- * Check if we are after an "if", "while", etc.
- * Also allow " } else".
- */
- if (cin_is_cinword(l) || cin_iselse((char_u *)skipwhite((char *)l))) {
+ // Check if we are after an "if", "while", etc.
+ // Also allow " } else".
+ 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)
@@ -3132,19 +2998,17 @@ int get_c_indent(void)
break;
}
- /*
- * If this is just above the line we are indenting, we
- * are finished.
- * while (not)
- * -> here;
- * Otherwise this indent can be used when the line
- * before this is terminated.
- * yyy;
- * if (stat)
- * while (not)
- * xxx;
- * -> here;
- */
+ // If this is just above the line we are indenting, we
+ // are finished.
+ // while (not)
+ // -> here;
+ // Otherwise this indent can be used when the line
+ // before this is terminated.
+ // yyy;
+ // if (stat)
+ // while (not)
+ // xxx;
+ // -> here;
amount = cur_amount;
if (theline[0] == '{') {
amount += curbuf->b_ind_open_extra;
@@ -3155,14 +3019,12 @@ int get_c_indent(void)
break;
}
- /*
- * Special trick: when expecting the while () after a
- * do, line up with the while()
- * do
- * x = 1;
- * -> here
- */
- l = (char_u *)skipwhite((char *)get_cursor_line_ptr());
+ // Special trick: when expecting the while () after a
+ // do, line up with the while()
+ // do
+ // x = 1;
+ // -> here
+ l = (char_u *)skipwhite(get_cursor_line_ptr());
if (cin_isdo(l)) {
if (whilelevel == 0) {
break;
@@ -3170,19 +3032,17 @@ int get_c_indent(void)
whilelevel--;
}
- /*
- * When searching for a terminated line, don't use the
- * one between the "if" and the matching "else".
- * Need to use the scope of this "else". XXX
- * If whilelevel != 0 continue looking for a "do {".
- */
+ // When searching for a terminated line, don't use the
+ // one between the "if" and the matching "else".
+ // Need to use the scope of this "else". XXX
+ // If whilelevel != 0 continue looking for a "do {".
if (cin_iselse(l) && whilelevel == 0) {
- /* If we're looking at "} else", let's make sure we
- * find the opening brace of the enclosing scope,
- * not the one from "if () {". */
+ // If we're looking at "} else", let's make sure we
+ // find the opening brace of the enclosing scope,
+ // not the one from "if () {".
if (*l == '}') {
curwin->w_cursor.col =
- (colnr_T)(l - get_cursor_line_ptr()) + 1;
+ (colnr_T)(l - (char_u *)get_cursor_line_ptr()) + 1;
}
if ((trypos = find_start_brace()) == NULL
@@ -3191,21 +3051,17 @@ int get_c_indent(void)
break;
}
}
- }
- /*
- * If we're below an unterminated line that is not an
- * "if" or something, we may line up with this line or
- * add something for a continuation line, depending on
- * the line before this one.
- */
- else {
- /*
- * Found two unterminated lines on a row, line up with
- * the last one.
- * c = 99 +
- * 100 +
- * -> here;
- */
+ } else {
+ // If we're below an unterminated line that is not an
+ // "if" or something, we may line up with this line or
+ // add something for a continuation line, depending on
+ // the line before this one.
+
+ // Found two unterminated lines on a row, line up with
+ // the last one.
+ // c = 99 +
+ // 100 +
+ // -> here;
if (lookfor == LOOKFOR_UNTERM) {
// When line ends in a comma add extra indent
if (terminated == ',') {
@@ -3215,11 +3071,11 @@ int get_c_indent(void)
}
if (lookfor == LOOKFOR_ENUM_OR_INIT) {
- /* Found two lines ending in ',', lineup with the
- * lowest one, but check for cpp base class
- * declaration/initialization, if it is an
- * opening brace or we are looking just for
- * enumerations/initializations. */
+ // Found two lines ending in ',', lineup with the
+ // lowest one, but check for cpp base class
+ // declaration/initialization, if it is an
+ // opening brace or we are looking just for
+ // enumerations/initializations.
if (terminated == ',') {
if (curbuf->b_ind_cpp_baseclass == 0) {
break;
@@ -3239,7 +3095,7 @@ int get_c_indent(void)
// line up with this line, remember its indent
// 100 + // NOLINT(whitespace/tab)
// -> here; // NOLINT(whitespace/tab)
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
amount = cur_amount;
n = (int)STRLEN(l);
@@ -3304,19 +3160,14 @@ int get_c_indent(void)
}
}
}
- }
- /*
- * Check if we are after a while (cond);
- * If so: Ignore until the matching "do".
- */
- else if (cin_iswhileofdo_end(terminated)) { // XXX
- /*
- * Found an unterminated line after a while ();, line up
- * with the last one.
- * while (cond);
- * 100 + <- line up with this one
- * -> here;
- */
+ // Check if we are after a while (cond);
+ // If so: Ignore until the matching "do".
+ } else if (cin_iswhileofdo_end(terminated)) { // XXX
+ // Found an unterminated line after a while ();, line up
+ // with the last one.
+ // while (cond);
+ // 100 + <- line up with this one
+ // -> here;
if (lookfor == LOOKFOR_UNTERM
|| lookfor == LOOKFOR_ENUM_OR_INIT) {
if (cont_amount > 0) {
@@ -3335,30 +3186,24 @@ int get_c_indent(void)
}
}
whilelevel++;
- }
- /*
- * We are after a "normal" statement.
- * If we had another statement we can stop now and use the
- * indent of that other statement.
- * Otherwise the indent of the current statement may be used,
- * search backwards for the next "normal" statement.
- */
- else {
- /*
- * Skip single break line, if before a switch label. It
- * may be lined up with the case label.
- */
+ } else {
+ // We are after a "normal" statement.
+ // If we had another statement we can stop now and use the
+ // indent of that other statement.
+ // Otherwise the indent of the current statement may be used,
+ // search backwards for the next "normal" statement.
+
+ // Skip single break line, if before a switch label. It
+ // may be lined up with the case label.
if (lookfor == LOOKFOR_NOBREAK
- && cin_isbreak((char_u *)skipwhite((char *)get_cursor_line_ptr()))) {
+ && cin_isbreak((char_u *)skipwhite(get_cursor_line_ptr()))) {
lookfor = LOOKFOR_ANY;
continue;
}
- /*
- * Handle "do {" line.
- */
+ // Handle "do {" line.
if (whilelevel > 0) {
- l = cin_skipcomment(get_cursor_line_ptr());
+ l = cin_skipcomment((char_u *)get_cursor_line_ptr());
if (cin_isdo(l)) {
amount = get_indent(); // XXX
whilelevel--;
@@ -3366,17 +3211,15 @@ int get_c_indent(void)
}
}
- /*
- * Found a terminated line above an unterminated line. Add
- * the amount for a continuation line.
- * x = 1;
- * y = foo +
- * -> here;
- * or
- * int x = 1;
- * int foo,
- * -> here;
- */
+ // Found a terminated line above an unterminated line. Add
+ // the amount for a continuation line.
+ // x = 1;
+ // y = foo +
+ // -> here;
+ // or
+ // int x = 1;
+ // int foo,
+ // -> here;
if (lookfor == LOOKFOR_UNTERM
|| lookfor == LOOKFOR_ENUM_OR_INIT) {
if (cont_amount > 0) {
@@ -3387,36 +3230,30 @@ int get_c_indent(void)
break;
}
- /*
- * Found a terminated line above a terminated line or "if"
- * etc. line. Use the amount of the line below us.
- * x = 1; x = 1;
- * if (asdf) y = 2;
- * while (asdf) ->here;
- * here;
- * ->foo;
- */
+ // Found a terminated line above a terminated line or "if"
+ // etc. line. Use the amount of the line below us.
+ // x = 1; x = 1;
+ // if (asdf) y = 2;
+ // while (asdf) ->here;
+ // here;
+ // ->foo;
if (lookfor == LOOKFOR_TERM) {
if (!lookfor_break && whilelevel == 0) {
break;
}
- }
- /*
- * First line above the one we're indenting is terminated.
- * To know what needs to be done look further backward for
- * a terminated line.
- */
- else {
- /*
- * position the cursor over the rightmost paren, so
- * that matching it will take us back to the start of
- * the line. Helps for:
- * func(asdr,
- * asdfasdf);
- * here;
- */
+ } else {
+ // First line above the one we're indenting is terminated.
+ // To know what needs to be done look further backward for
+ // a terminated line.
+
+ // position the cursor over the rightmost paren, so
+ // that matching it will take us back to the start of
+ // the line. Helps for:
+ // func(asdr,
+ // asdfasdf);
+ // here;
term_again:
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
if (find_last_paren(l, '(', ')')
&& (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL) {
// Check if we are on a case label now. This is
@@ -3424,7 +3261,7 @@ term_again:
// case xx: if ( asdf &&
// asdf)
curwin->w_cursor = *trypos;
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
if (cin_iscase(l, false) || cin_isscopedecl(l)) {
curwin->w_cursor.lnum++;
curwin->w_cursor.col = 0;
@@ -3432,21 +3269,18 @@ term_again:
}
}
- /* When aligning with the case statement, don't align
- * with a statement after it.
- * case 1: { <-- don't use this { position
- * stat;
- * }
- * case 2:
- * stat;
- * }
- */
+ // When aligning with the case statement, don't align
+ // with a statement after it.
+ // case 1: { <-- don't use this { position
+ // stat;
+ // }
+ // case 2:
+ // stat;
+ // }
iscase = curbuf->b_ind_keep_case_label && cin_iscase(l, false);
- /*
- * Get indent and pointer to text for current line,
- * ignoring any jump label.
- */
+ // Get indent and pointer to text for current line,
+ // ignoring any jump label.
amount = skip_label(curwin->w_cursor.lnum, &l);
if (theline[0] == '{') {
@@ -3459,14 +3293,12 @@ term_again:
}
lookfor = iscase ? LOOKFOR_ANY : LOOKFOR_TERM;
- /*
- * When a terminated line starts with "else" skip to
- * the matching "if":
- * else 3;
- * indent this;
- * Need to use the scope of this "else". XXX
- * If whilelevel != 0 continue looking for a "do {".
- */
+ // When a terminated line starts with "else" skip to
+ // the matching "if":
+ // else 3;
+ // indent this;
+ // Need to use the scope of this "else". XXX
+ // If whilelevel != 0 continue looking for a "do {".
if (lookfor == LOOKFOR_TERM
&& *l != '}'
&& cin_iselse(l)
@@ -3479,17 +3311,15 @@ term_again:
continue;
}
- /*
- * If we're at the end of a block, skip to the start of
- * that block.
- */
- l = get_cursor_line_ptr();
+ // If we're at the end of a block, skip to the start of
+ // that block.
+ l = (char_u *)get_cursor_line_ptr();
if (find_last_paren(l, '{', '}') // XXX
&& (trypos = find_start_brace()) != NULL) {
curwin->w_cursor = *trypos;
// if not "else {" check for terminated again
// but skip block for "} else {"
- l = cin_skipcomment(get_cursor_line_ptr());
+ l = cin_skipcomment((char_u *)get_cursor_line_ptr());
if (*l == '}' || !cin_iselse(l)) {
goto term_again;
}
@@ -3529,13 +3359,11 @@ term_again:
amount = curbuf->b_ind_first_open;
goto theend;
}
- /*
- * If the NEXT line is a function declaration, the current
- * line needs to be indented as a function type spec.
- * Don't do this if the current line looks like a comment or if the
- * current line is terminated, ie. ends in ';', or if the current line
- * contains { or }: "void f() {\n if (1)"
- */
+ // If the NEXT line is a function declaration, the current
+ // line needs to be indented as a function type spec.
+ // Don't do this if the current line looks like a comment or if the
+ // current line is terminated, ie. ends in ';', or if the current line
+ // contains { or }: "void f() {\n if (1)"
if (cur_curpos.lnum < curbuf->b_ml.ml_line_count
&& !cin_nocode(theline)
&& vim_strchr((char *)theline, '{') == NULL
@@ -3555,7 +3383,7 @@ term_again:
curwin->w_cursor.lnum--;
curwin->w_cursor.col = 0;
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
// If we're in a comment or raw string now, skip to the start
// of it.
@@ -3571,7 +3399,7 @@ term_again:
n = 0;
if (curbuf->b_ind_cpp_baseclass != 0) {
n = cin_is_cpp_baseclass(&cache_cpp_baseclass);
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
}
if (n) {
// XXX
@@ -3590,18 +3418,16 @@ term_again:
continue;
}
- /*
- * If the previous line ends in ',', use one level of
- * indentation:
- * int foo,
- * bar;
- * do this before checking for '}' in case of eg.
- * enum foobar
- * {
- * ...
- * } foo,
- * bar;
- */
+ // If the previous line ends in ',', use one level of
+ // indentation:
+ // int foo,
+ // bar;
+ // do this before checking for '}' in case of eg.
+ // enum foobar
+ // {
+ // ...
+ // } foo,
+ // bar;
if (cin_ends_in(l, (char_u *)",", NULL)
|| (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\')) {
// take us back to opening paren
@@ -3610,14 +3436,13 @@ term_again:
curwin->w_cursor = *trypos;
}
- /* For a line ending in ',' that is a continuation line go
- * back to the first line with a backslash:
- * char *foo = "bla\
- * bla",
- * here;
- */
+ // For a line ending in ',' that is a continuation line go
+ // back to the first line with a backslash:
+ // char *foo = "bla{backslash}
+ // bla",
+ // here;
while (n == 0 && curwin->w_cursor.lnum > 1) {
- l = ml_get(curwin->w_cursor.lnum - 1);
+ l = (char_u *)ml_get(curwin->w_cursor.lnum - 1);
if (*l == NUL || l[STRLEN(l) - 1] != '\\') {
break;
}
@@ -3636,19 +3461,15 @@ term_again:
break;
}
- /*
- * If the line looks like a function declaration, and we're
- * not in a comment, put it the left margin.
- */
+ // If the line looks like a function declaration, and we're
+ // not in a comment, put it the left margin.
if (cin_isfuncdecl(NULL, cur_curpos.lnum, 0)) { // XXX
break;
}
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
- /*
- * Finding the closing '}' of a previous function. Put
- * current line at the left margin. For when 'cino' has "fs".
- */
+ // Finding the closing '}' of a previous function. Put
+ // current line at the left margin. For when 'cino' has "fs".
if (*skipwhite((char *)l) == '}') {
break;
}
@@ -3671,16 +3492,14 @@ term_again:
break;
}
- /*
- * Find a line only has a semicolon that belongs to a previous
- * line ending in '}', e.g. before an #endif. Don't increase
- * indent then.
- */
+ // Find a line only has a semicolon that belongs to a previous
+ // line ending in '}', e.g. before an #endif. Don't increase
+ // indent then.
if (*(look = (char_u *)skipwhite((char *)l)) == ';' && cin_nocode(look + 1)) {
pos_T curpos_save = curwin->w_cursor;
while (curwin->w_cursor.lnum > 1) {
- look = ml_get(--curwin->w_cursor.lnum);
+ look = (char_u *)ml_get(--curwin->w_cursor.lnum);
if (!(cin_nocode(look)
|| cin_ispreproc_cont(&look, &curwin->w_cursor.lnum, &amount))) {
break;
@@ -3694,39 +3513,33 @@ term_again:
curwin->w_cursor = curpos_save;
}
- /*
- * If the PREVIOUS line is a function declaration, the current
- * line (and the ones that follow) needs to be indented as
- * parameters.
- */
+ // If the PREVIOUS line is a function declaration, the current
+ // line (and the ones that follow) needs to be indented as
+ // parameters.
if (cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0)) {
amount = curbuf->b_ind_param;
break;
}
- /*
- * If the previous line ends in ';' and the line before the
- * previous line ends in ',' or '\', ident to column zero:
- * int foo,
- * bar;
- * indent_to_0 here;
- */
+ // If the previous line ends in ';' and the line before the
+ // previous line ends in ',' or '\', ident to column zero:
+ // int foo,
+ // bar;
+ // indent_to_0 here;
if (cin_ends_in(l, (char_u *)";", NULL)) {
- l = ml_get(curwin->w_cursor.lnum - 1);
+ l = (char_u *)ml_get(curwin->w_cursor.lnum - 1);
if (cin_ends_in(l, (char_u *)",", NULL)
|| (*l != NUL && l[STRLEN(l) - 1] == '\\')) {
break;
}
- l = get_cursor_line_ptr();
+ l = (char_u *)get_cursor_line_ptr();
}
- /*
- * Doesn't look like anything interesting -- so just
- * use the indent of this line.
- *
- * Position the cursor over the rightmost paren, so that
- * matching it will take us back to the start of the line.
- */
+ // Doesn't look like anything interesting -- so just
+ // use the indent of this line.
+ //
+ // Position the cursor over the rightmost paren, so that
+ // matching it will take us back to the start of the line.
(void)find_last_paren(l, '(', ')');
if ((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL) {
@@ -3747,7 +3560,7 @@ term_again:
// char *foo = "asdf{backslash}
// here";
if (cur_curpos.lnum > 1) {
- l = ml_get(cur_curpos.lnum - 1);
+ l = (char_u *)ml_get(cur_curpos.lnum - 1);
if (*l != NUL && l[STRLEN(l) - 1] == '\\') {
cur_amount = cin_get_equal_amount(cur_curpos.lnum - 1);
if (cur_amount > 0) {
@@ -3794,7 +3607,7 @@ static int find_match(int lookfor, linenr_T ourscope)
curwin->w_cursor.lnum--;
curwin->w_cursor.col = 0;
- look = cin_skipcomment(get_cursor_line_ptr());
+ look = cin_skipcomment((char_u *)get_cursor_line_ptr());
if (!cin_iselse(look)
&& !cin_isif(look)
&& !cin_isdo(look) // XXX
@@ -3802,39 +3615,31 @@ static int find_match(int lookfor, linenr_T ourscope)
continue;
}
- /*
- * if we've gone outside the braces entirely,
- * we must be out of scope...
- */
+ // if we've gone outside the braces entirely,
+ // we must be out of scope...
theirscope = find_start_brace(); // XXX
if (theirscope == NULL) {
break;
}
- /*
- * and if the brace enclosing this is further
- * back than the one enclosing the else, we're
- * out of luck too.
- */
+ // and if the brace enclosing this is further
+ // back than the one enclosing the else, we're
+ // out of luck too.
if (theirscope->lnum < ourscope) {
break;
}
- /*
- * and if they're enclosed in a *deeper* brace,
- * then we can ignore it because it's in a
- * different scope...
- */
+ // and if they're enclosed in a *deeper* brace,
+ // then we can ignore it because it's in a
+ // different scope...
if (theirscope->lnum > ourscope) {
continue;
}
- /*
- * if it was an "else" (that's not an "else if")
- * then we need to go back to another if, so
- * increment elselevel
- */
- look = cin_skipcomment(get_cursor_line_ptr());
+ // if it was an "else" (that's not an "else if")
+ // then we need to go back to another if, so
+ // increment elselevel
+ look = cin_skipcomment((char_u *)get_cursor_line_ptr());
if (cin_iselse(look)) {
mightbeif = cin_skipcomment(look + 4);
if (!cin_isif(mightbeif)) {
@@ -3843,23 +3648,19 @@ static int find_match(int lookfor, linenr_T ourscope)
continue;
}
- /*
- * if it was a "while" then we need to go back to
- * another "do", so increment whilelevel. XXX
- */
+ // if it was a "while" then we need to go back to
+ // another "do", so increment whilelevel. XXX
if (cin_iswhileofdo(look, curwin->w_cursor.lnum)) {
whilelevel++;
continue;
}
// If it's an "if" decrement elselevel
- look = cin_skipcomment(get_cursor_line_ptr());
+ look = cin_skipcomment((char_u *)get_cursor_line_ptr());
if (cin_isif(look)) {
- elselevel--;
- /*
- * When looking for an "if" ignore "while"s that
- * get in the way.
- */
+ elselevel--; // NOLINT(readability/braces)
+ // When looking for an "if" ignore "while"s that
+ // get in the way.
if (elselevel == 0 && lookfor == LOOKFOR_IF) {
whilelevel = 0;
}
@@ -3870,11 +3671,9 @@ static int find_match(int lookfor, linenr_T ourscope)
whilelevel--;
}
- /*
- * if we've used up all the elses, then
- * this must be the if that we want!
- * match the indent level of that if.
- */
+ // if we've used up all the elses, then
+ // this must be the if that we want!
+ // match the indent level of that if.
if (elselevel <= 0 && whilelevel <= 0) {
return OK;
}
@@ -3882,9 +3681,7 @@ static int find_match(int lookfor, linenr_T ourscope)
return FAIL;
}
-/*
- * Do C or expression indenting on the current line.
- */
+// Do C or expression indenting on the current line.
void do_c_expr_indent(void)
{
if (*curbuf->b_p_inde != NUL) {
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..a5e7929525 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"
@@ -131,15 +132,30 @@ typedef struct compl_S compl_T;
struct compl_S {
compl_T *cp_next;
compl_T *cp_prev;
- char_u *cp_str; ///< matched text
- char_u *(cp_text[CPT_COUNT]); ///< text for the menu
+ char *cp_str; ///< matched text
+ char *(cp_text[CPT_COUNT]); ///< text for the menu
typval_T cp_user_data;
- char_u *cp_fname; ///< file containing the match, allocated when
+ char *cp_fname; ///< file containing the match, allocated when
///< cp_flags has CP_FREE_FNAME
int cp_flags; ///< CP_ values
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;
@@ -174,7 +191,7 @@ static bool compl_enter_selects = false;
/// When "compl_leader" is not NULL only matches that start with this string
/// are used.
-static char_u *compl_leader = NULL;
+static char *compl_leader = NULL;
static bool compl_get_longest = false; ///< put longest common string in compl_leader
@@ -203,19 +220,36 @@ 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
+static char *compl_orig_text = NULL; ///< text as it was before
///< completion started
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 = (char_u *)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 = (char_u *)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 = (char_u *)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 (char_u *)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;
+ const char_u *p = (char_u *)compl_orig_text;
+ 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);
- }
- }
+ int min_len = char_len < compl_char_len ? char_len : compl_char_len;
- // 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);
- }
- }
-
- // 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,29 +720,37 @@ 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((char *)str, len, (char *)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
/// returned in case of error.
-static int ins_compl_add(char_u *const str, int len, char_u *const fname,
- char_u *const *const cptext, const bool cptext_allocated,
- typval_T *user_data, const Direction cdir, int flags_arg, const bool adup)
+static int ins_compl_add(char *const str, int len, char *const fname, char *const *const cptext,
+ const bool cptext_allocated, typval_T *user_data, const Direction cdir,
+ int flags_arg, const bool adup)
FUNC_ATTR_NONNULL_ARG(1)
{
compl_T *match;
@@ -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.
@@ -681,7 +802,7 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname,
if (flags & CP_ORIGINAL_TEXT) {
match->cp_number = 0;
}
- match->cp_str = vim_strnsave(str, (size_t)len);
+ match->cp_str = xstrnsave(str, (size_t)len);
// match-fname is:
// - compl_curr_match->cp_fname if it is a string equal to fname.
@@ -690,10 +811,10 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname,
if (fname != NULL
&& compl_curr_match != NULL
&& compl_curr_match->cp_fname != NULL
- && STRCMP(fname, compl_curr_match->cp_fname) == 0) {
+ && strcmp(fname, compl_curr_match->cp_fname) == 0) {
match->cp_fname = compl_curr_match->cp_fname;
} else if (fname != NULL) {
- match->cp_fname = vim_strsave(fname);
+ match->cp_fname = xstrdup(fname);
flags |= CP_FREE_FNAME;
} else {
match->cp_fname = NULL;
@@ -708,9 +829,7 @@ static int ins_compl_add(char_u *const str, int len, char_u *const fname,
continue;
}
if (*cptext[i] != NUL) {
- match->cp_text[i] = (cptext_allocated
- ? cptext[i]
- : (char_u *)xstrdup((char *)cptext[i]));
+ match->cp_text[i] = (cptext_allocated ? cptext[i] : xstrdup(cptext[i]));
} else if (cptext_allocated) {
xfree(cptext[i]);
}
@@ -721,7 +840,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) {
@@ -776,7 +896,8 @@ 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);
+ compl_leader = xstrdup(match->cp_str);
+
had_match = (curwin->w_cursor.col > compl_col);
ins_compl_delete();
ins_bytes(compl_leader + get_compl_len());
@@ -788,40 +909,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 = (char_u *)compl_leader;
+ s = (char_u *)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(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.
@@ -832,7 +955,7 @@ static void ins_compl_add_matches(int num_matches, char **matches, int icase)
Direction dir = compl_direction;
for (int i = 0; i < num_matches && add_r != FAIL; i++) {
- if ((add_r = ins_compl_add((char_u *)matches[i], -1, NULL, NULL, false, NULL, dir,
+ if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, false, NULL, dir,
CP_FAST | (icase ? CP_ICASE : 0),
false)) == OK) {
// If dir was BACKWARD then honor it just once.
@@ -846,20 +969,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 +1006,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 +1022,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 +1035,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 +1045,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 +1078,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 +1108,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, (char_u *)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, (char_u *)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 = (char_u *)compl->cp_text[CPT_ABBR];
+ } else {
+ compl_match_array[i].pum_text = (char_u *)compl->cp_str;
+ }
+ compl_match_array[i].pum_kind = (char_u *)compl->cp_text[CPT_KIND];
+ compl_match_array[i].pum_info = (char_u *)compl->cp_text[CPT_INFO];
+ if (compl->cp_text[CPT_MENU] != NULL) {
+ compl_match_array[i++].pum_extra = (char_u *)compl->cp_text[CPT_MENU];
+ } else {
+ compl_match_array[i++].pum_extra = (char_u *)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++) {
- 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]) {
+ for (int i = 0; i < compl_match_arraysize; i++) {
+ if (compl_match_array[i].pum_text == (char_u *)compl_shown_match->cp_str
+ || compl_match_array[i].pum_text == (char_u *)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 +1266,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
@@ -1195,7 +1332,7 @@ static void ins_compl_dictionaries(char_u *dict_start, char_u *pat, int flags, i
// backticks (for security, the 'dict' option may have been set in
// a modeline).
copy_option_part(&dict, buf, LSIZE, ",");
- if (!thesaurus && STRCMP(buf, "spell") == 0) {
+ if (!thesaurus && strcmp(buf, "spell") == 0) {
count = -1;
} else if (vim_strchr(buf, '`') != NULL
|| expand_wildcards(1, &buf, &count, &files,
@@ -1212,7 +1349,7 @@ static void ins_compl_dictionaries(char_u *dict_start, char_u *pat, int flags, i
} else {
ptr = pat;
}
- spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0);
+ spell_dump_compl((char *)ptr, regmatch.rm_ic, &dir, 0);
} else if (count > 0) { // avoid warning for using "files" uninit
ins_compl_files(count, files, thesaurus, flags,
&regmatch, (char_u *)buf, &dir);
@@ -1231,6 +1368,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,52 +1440,23 @@ 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];
+ ptr = (char_u *)regmatch->startp[0];
if (ctrl_x_mode_line_or_eval()) {
ptr = find_line_end(ptr);
} else {
ptr = find_word_end(ptr);
}
- add_r = ins_compl_add_infercase(regmatch->startp[0],
- (int)(ptr - regmatch->startp[0]),
+ add_r = ins_compl_add_infercase((char_u *)regmatch->startp[0],
+ (int)(ptr - (char_u *)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,
+ (char_u *)regmatch->startp[0]);
}
if (add_r == OK) {
// if dir was BACKWARD then honor it just once
@@ -1391,12 +1547,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,14 +1607,20 @@ 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
/// to be got from the user.
int ins_compl_bs(void)
{
- char_u *line = get_cursor_line_ptr();
- char_u *p = line + curwin->w_cursor.col;
+ char *line = get_cursor_line_ptr();
+ char *p = line + curwin->w_cursor.col;
MB_PTR_BACK(line, p);
ptrdiff_t p_off = p - line;
@@ -1484,13 +1647,13 @@ int ins_compl_bs(void)
line = get_cursor_line_ptr();
xfree(compl_leader);
- compl_leader = vim_strnsave(line + compl_col, (size_t)(p_off - (ptrdiff_t)compl_col));
+ compl_leader = xstrnsave(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;
}
@@ -1567,7 +1730,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);
}
@@ -1578,8 +1741,8 @@ void ins_compl_addleader(int c)
}
xfree(compl_leader);
- compl_leader = vim_strnsave(get_cursor_line_ptr() + compl_col,
- (size_t)(curwin->w_cursor.col - compl_col));
+ compl_leader = xstrnsave(get_cursor_line_ptr() + compl_col,
+ (size_t)(curwin->w_cursor.col - compl_col));
ins_compl_new_leader();
}
@@ -1599,19 +1762,19 @@ static void ins_compl_restart(void)
}
/// Set the first match, the original text.
-static void ins_compl_set_original_text(char_u *str)
+static void ins_compl_set_original_text(char *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);
+ compl_first_match->cp_str = xstrdup(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);
+ compl_first_match->cp_prev->cp_str = xstrdup(str);
}
}
@@ -1624,24 +1787,24 @@ void ins_compl_addfrommatch(void)
int c;
compl_T *cp;
assert(compl_shown_match != NULL);
- p = compl_shown_match->cp_str;
+ p = (char_u *)compl_shown_match->cp_str;
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, (char_u *)compl_leader, STRLEN(compl_leader))) {
+ p = (char_u *)cp->cp_str;
+ break;
}
- } else {
+ }
+ if (p == NULL || (int)STRLEN(p) <= len) {
return;
}
}
@@ -1650,6 +1813,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 = (char_u *)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 = (char_u *)compl_leader;
+ } else if (compl_first_match != NULL) {
+ p = (char_u *)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 +2064,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 +2103,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 +2135,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
@@ -1958,16 +2166,16 @@ static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg)
if (ptr == NULL) {
if (compl_leader != NULL) {
- ptr = compl_leader;
+ ptr = (char_u *)compl_leader;
} else {
return; // nothing to do
}
}
if (compl_orig_text != NULL) {
- p = compl_orig_text;
+ p = (char_u *)compl_orig_text;
for (len = 0; p[len] != NUL && p[len] == ptr[len]; len++) {}
if (len > 0) {
- len -= utf_head_off(p, p + len);
+ len -= utf_head_off((char *)p, (char *)p + len);
}
for (p += len; *p != NUL; MB_PTR_ADV(p)) {
AppendCharToRedobuff(K_BS);
@@ -2010,16 +2218,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 +2355,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 *)word, -1, NULL, cptext, true,
+ &user_data, dir, flags, dup);
+ if (status != OK) {
+ tv_clear(&user_data);
+ }
+ return status;
}
/// Add completions from a list.
@@ -2215,8 +2428,8 @@ static void set_completion(colnr_T startcol, list_T *list)
compl_col = startcol;
compl_length = (int)curwin->w_cursor.col - (int)startcol;
// compl_pattern doesn't need to be set
- compl_orig_text = vim_strnsave(get_cursor_line_ptr() + compl_col,
- (size_t)compl_length);
+ compl_orig_text = xstrnsave(get_cursor_line_ptr() + compl_col,
+ (size_t)compl_length);
if (p_ic) {
flags |= CP_ICASE;
}
@@ -2256,7 +2469,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 +2493,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 +2518,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 +2550,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;
@@ -2375,15 +2588,15 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
; item = TV_LIST_ITEM_NEXT(what_list, item)) {
const char *what = tv_get_string(TV_LIST_ITEM_TV(item));
- if (STRCMP(what, "mode") == 0) {
+ if (strcmp(what, "mode") == 0) {
what_flag |= CI_WHAT_MODE;
- } else if (STRCMP(what, "pum_visible") == 0) {
+ } else if (strcmp(what, "pum_visible") == 0) {
what_flag |= CI_WHAT_PUM_VISIBLE;
- } else if (STRCMP(what, "items") == 0) {
+ } else if (strcmp(what, "items") == 0) {
what_flag |= CI_WHAT_ITEMS;
- } else if (STRCMP(what, "selected") == 0) {
+ } else if (strcmp(what, "selected") == 0) {
what_flag |= CI_WHAT_SELECTED;
- } else if (STRCMP(what, "inserted") == 0) {
+ } else if (strcmp(what, "inserted") == 0) {
what_flag |= CI_WHAT_INSERTED;
}
}
@@ -2406,7 +2619,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 +2635,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 +2654,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 +2677,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 = (char_u *)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 = (char_u *)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 = (char_u *)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 = (char_u *)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 +3161,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 +3172,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 +3209,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 +3224,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 +3232,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 +3241,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 +3256,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 +3268,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,
+ (char_u *)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, (char_u *)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, (char_u *)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 +3300,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;
@@ -2964,7 +3320,7 @@ void ins_compl_delete(void)
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);
+ 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 +3329,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 = 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,
+ 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 +3401,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 +3409,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,10 +3427,10 @@ 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))) {
+ (char_u *)compl_leader, STRLEN(compl_leader))) {
todo++;
} else {
// Remember a matching item.
@@ -3119,6 +3447,68 @@ 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());
@@ -3154,31 +3544,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;
@@ -3328,46 +3695,46 @@ static bool ins_compl_use_match(int c)
/// completion)
/// Sets the global variables: compl_col, compl_length and compl_pattern.
/// Uses the global variables: compl_cont_status and ctrl_x_mode
-static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
+static int get_normal_compl_info(char *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;
}
if (p_ic) {
- compl_pattern = (char *)str_foldcase(line + compl_col, compl_length, NULL, 0);
+ compl_pattern = (char *)str_foldcase((char_u *)line + compl_col, compl_length, NULL, 0);
} else {
- compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length);
+ compl_pattern = xstrnsave(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
- compl_pattern = xmalloc(quote_meta(NULL, line + compl_col,
- compl_length) + 2);
- if (!vim_iswordp(line + compl_col)
- || (compl_col > 0 && (vim_iswordp(mb_prevptr(line, line + compl_col))))) {
+ compl_pattern = xmalloc(quote_meta(NULL, (char_u *)line + compl_col, compl_length) + 2);
+ if (!vim_iswordp((char_u *)line + compl_col)
+ || (compl_col > 0
+ && (vim_iswordp(mb_prevptr((char_u *)line, (char_u *)line + compl_col))))) {
prefix = (char_u *)"";
}
STRCPY(compl_pattern, prefix);
(void)quote_meta((char_u *)compl_pattern + STRLEN(prefix),
- line + compl_col, compl_length);
+ (char_u *)line + compl_col, compl_length);
} else if (--startcol < 0
- || !vim_iswordp(mb_prevptr(line, line + startcol + 1))) {
+ || !vim_iswordp(mb_prevptr((char_u *)line, (char_u *)line + startcol + 1))) {
// Match any word of at least two chars
- compl_pattern = (char *)vim_strsave((char_u *)"\\<\\k\\k");
+ compl_pattern = xstrdup("\\<\\k\\k");
compl_col += curs_col;
compl_length = 0;
} else {
// Search the point of change class of multibyte character
// or not a word single byte character backward.
startcol -= utf_head_off(line, line + startcol);
- int base_class = mb_get_class(line + startcol);
+ int base_class = mb_get_class((char_u *)line + startcol);
while (--startcol >= 0) {
int head_off = utf_head_off(line, line + startcol);
- if (base_class != mb_get_class(line + startcol - head_off)) {
+ if (base_class != mb_get_class((char_u *)line + startcol - head_off)) {
break;
}
startcol -= head_off;
@@ -3380,13 +3747,13 @@ static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
// xmalloc(7) is enough -- Acevedo
compl_pattern = xmalloc(7);
STRCPY(compl_pattern, "\\<");
- (void)quote_meta((char_u *)compl_pattern + 2, line + compl_col, 1);
+ (void)quote_meta((char_u *)compl_pattern + 2, (char_u *)line + compl_col, 1);
STRCAT(compl_pattern, "\\k");
} else {
- compl_pattern = xmalloc(quote_meta(NULL, line + compl_col,
+ compl_pattern = xmalloc(quote_meta(NULL, (char_u *)line + compl_col,
compl_length) + 2);
STRCPY(compl_pattern, "\\<");
- (void)quote_meta((char_u *)compl_pattern + 2, line + compl_col, compl_length);
+ (void)quote_meta((char_u *)compl_pattern + 2, (char_u *)line + compl_col, compl_length);
}
}
@@ -3396,7 +3763,7 @@ static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
/// Get the pattern, column and length for whole line completion or for the
/// complete() function.
/// Sets the global variables: compl_col, compl_length and compl_pattern.
-static int get_wholeline_compl_info(char_u *line, colnr_T curs_col)
+static int get_wholeline_compl_info(char *line, colnr_T curs_col)
{
compl_col = (colnr_T)getwhitecols(line);
compl_length = (int)curs_col - (int)compl_col;
@@ -3404,9 +3771,9 @@ static int get_wholeline_compl_info(char_u *line, colnr_T curs_col)
compl_length = 0;
}
if (p_ic) {
- compl_pattern = (char *)str_foldcase(line + compl_col, compl_length, NULL, 0);
+ compl_pattern = (char *)str_foldcase((char_u *)line + compl_col, compl_length, NULL, 0);
} else {
- compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length);
+ compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length);
}
return OK;
@@ -3433,16 +3800,16 @@ static int get_filename_compl_info(char_u *line, int startcol, colnr_T curs_col)
compl_col += startcol;
compl_length = (int)curs_col - startcol;
- compl_pattern = (char *)addstar(line + compl_col, (size_t)compl_length, EXPAND_FILES);
+ compl_pattern = addstar((char *)line + compl_col, (size_t)compl_length, EXPAND_FILES);
return OK;
}
/// Get the pattern, column and length for command-line completion.
/// Sets the global variables: compl_col, compl_length and compl_pattern.
-static int get_cmdline_compl_info(char_u *line, colnr_T curs_col)
+static int get_cmdline_compl_info(char *line, colnr_T curs_col)
{
- compl_pattern = (char *)vim_strnsave(line, (size_t)curs_col);
+ compl_pattern = xstrnsave(line, (size_t)curs_col);
set_cmd_context(&compl_xp, (char_u *)compl_pattern, (int)STRLEN(compl_pattern), curs_col, false);
if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL
|| compl_xp.xp_context == EXPAND_NOTHING) {
@@ -3510,7 +3877,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;
@@ -3524,9 +3891,9 @@ static int get_userdefined_compl_info(colnr_T curs_col)
// Setup variables for completion. Need to obtain "line" again,
// it may have become invalid.
- char_u *line = ml_get(curwin->w_cursor.lnum);
+ char *line = ml_get(curwin->w_cursor.lnum);
compl_length = curs_col - compl_col;
- compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length);
+ compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length);
return OK;
}
@@ -3550,36 +3917,44 @@ static int get_spell_compl_info(int startcol, colnr_T curs_col)
compl_length = (int)curs_col - compl_col;
}
// Need to obtain "line" again, it may have become invalid.
- char_u *line = ml_get(curwin->w_cursor.lnum);
- compl_pattern = (char *)vim_strnsave(line + compl_col, (size_t)compl_length);
+ char *line = ml_get(curwin->w_cursor.lnum);
+ compl_pattern = xstrnsave(line + compl_col, (size_t)compl_length);
return OK;
}
/// 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()
|| ((ctrl_x_mode & CTRL_X_WANT_IDENT)
&& !thesaurus_func_complete(ctrl_x_mode))) {
- return get_normal_compl_info(line, startcol, curs_col);
+ return get_normal_compl_info((char *)line, startcol, curs_col);
} else if (ctrl_x_mode_line_or_eval()) {
- return get_wholeline_compl_info(line, curs_col);
+ return get_wholeline_compl_info((char *)line, curs_col);
} else if (ctrl_x_mode_files()) {
return get_filename_compl_info(line, startcol, curs_col);
} else if (ctrl_x_mode == CTRL_X_CMDLINE) {
- return get_cmdline_compl_info(line, curs_col);
+ return get_cmdline_compl_info((char *)line, curs_col);
} else if (ctrl_x_mode_function() || ctrl_x_mode_omni()
|| thesaurus_func_complete(ctrl_x_mode)) {
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 +3963,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;
+ // 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 {
+ // 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;
}
-
- 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
+ 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;
- }
- } else {
+ 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)) { // 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;
- }
-
- // 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;
- }
- // If "line" was changed while getting completion info get it again.
- if (line_invalid) {
- line = ml_get(curwin->w_cursor.lnum);
- }
+/// start insert mode completion
+static int ins_compl_start(void)
+{
+ const bool save_did_ai = did_ai;
- 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;
+ // First time we hit ^N or ^P (in a row, I mean)
- 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;
- }
+ did_ai = false;
+ did_si = false;
+ can_si = false;
+ can_si_back = false;
+ if (stop_arrow() == FAIL) {
+ return FAIL;
+ }
- 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));
- }
+ char *line = ml_get(curwin->w_cursor.lnum);
+ colnr_T curs_col = curwin->w_cursor.col;
+ compl_pending = 0;
- // If any of the original typed text has been changed we need to fix
- // the redo buffer.
- ins_compl_fixRedoBufForLeader(NULL);
+ 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((char_u *)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((char_u *)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 = xstrnsave(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 +4172,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 +4196,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 +4273,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..a3763ea9bb 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
@@ -650,7 +650,7 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const
if (*bp == '-') {
last_dash = bp;
if (bp + 1 <= end) {
- l = utfc_ptr2len_len(bp + 1, (int)(end - bp) + 1);
+ l = utfc_ptr2len_len((char *)bp + 1, (int)(end - bp) + 1);
// Anything accepted, like <C-?>.
// <C-"> or <M-"> are not special in strings as " is
// the string delimiter. With a backslash it works: <M-\">
@@ -665,7 +665,7 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const
if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') {
bp += 3; // skip t_xx, xx may be '-' or '>'
} else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) {
- vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true);
+ vim_str2nr((char *)bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true);
if (l == 0) {
emsg(_(e_invarg));
return 0;
@@ -695,7 +695,7 @@ int find_special_key(const char_u **const srcp, const size_t src_len, int *const
if (STRNICMP(last_dash + 1, "char-", 5) == 0
&& ascii_isdigit(last_dash[6])) {
// <Char-123> or <Char-033> or <Char-0x33>
- vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true);
+ vim_str2nr((char *)last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true);
if (l == 0) {
emsg(_(e_invarg));
return 0;
@@ -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);
@@ -993,7 +993,7 @@ char *replace_termcodes(const char *const from, const size_t from_len, char **co
}
// skip multibyte char correctly
- for (i = utfc_ptr2len_len(src, (int)(end - src) + 1); i > 0; i--) {
+ for (i = utfc_ptr2len_len((char *)src, (int)(end - src) + 1); i > 0; i--) {
// If the character is K_SPECIAL, replace it with K_SPECIAL
// KS_SPECIAL KE_FILLER.
if (*src == K_SPECIAL) {
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/converter.c b/src/nvim/lua/converter.c
index 49d49f76b9..735a75a6f1 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -385,15 +385,12 @@ nlua_pop_typval_table_processing_end:
break;
}
case LUA_TFUNCTION: {
- LuaCFunctionState *state = xmalloc(sizeof(LuaCFunctionState));
- state->lua_callable.func_ref = nlua_ref_global(lstate, -1);
+ LuaRef func = nlua_ref_global(lstate, -1);
- char_u *name = register_cfunc(&nlua_CFunction_func_call,
- &nlua_CFunction_func_free,
- state);
+ char *name = (char *)register_luafunc(func);
cur.tv->v_type = VAR_FUNC;
- cur.tv->vval.v_string = (char *)vim_strsave(name);
+ cur.tv->vval.v_string = xstrdup(name);
break;
}
case LUA_TUSERDATA: {
@@ -476,8 +473,8 @@ static bool typval_conv_special = false;
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
do { \
ufunc_T *fp = find_func(fun); \
- if (fp != NULL && fp->uf_cb == nlua_CFunction_func_call) { \
- nlua_pushref(lstate, ((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref); \
+ if (fp != NULL && fp->uf_flags & FC_LUAREF) { \
+ nlua_pushref(lstate, fp->uf_luaref); \
} else { \
TYPVAL_ENCODE_CONV_NIL(tv); \
} \
diff --git a/src/nvim/lua/converter.h b/src/nvim/lua/converter.h
index f6a85900ba..ddc0acfbfa 100644
--- a/src/nvim/lua/converter.h
+++ b/src/nvim/lua/converter.h
@@ -9,14 +9,6 @@
#include "nvim/eval/typval.h"
#include "nvim/func_attr.h"
-typedef struct {
- LuaRef func_ref;
-} LuaCallable;
-
-typedef struct {
- LuaCallable lua_callable;
-} LuaCFunctionState;
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "lua/converter.h.generated.h"
#endif
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index d1d1480696..78ac051308 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -7,6 +7,7 @@
#include <tree_sitter/api.h>
#include "luv/luv.h"
+#include "nvim/api/extmark.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
@@ -40,6 +41,9 @@
#include "nvim/os/os.h"
#include "nvim/profile.h"
#include "nvim/runtime.h"
+#include "nvim/screen.h"
+#include "nvim/ui.h"
+#include "nvim/ui_compositor.h"
#include "nvim/undo.h"
#include "nvim/usercmd.h"
#include "nvim/version.h"
@@ -589,6 +593,71 @@ static bool nlua_init_packages(lua_State *lstate)
return true;
}
+/// "vim.ui_attach(ns_id, {ext_foo=true}, cb)" function
+static int nlua_ui_attach(lua_State *lstate)
+ FUNC_ATTR_NONNULL_ALL
+{
+ uint32_t ns_id = (uint32_t)luaL_checkinteger(lstate, 1);
+
+ if (!ns_initialized(ns_id)) {
+ return luaL_error(lstate, "invalid ns_id");
+ }
+ if (!lua_istable(lstate, 2)) {
+ return luaL_error(lstate, "ext_widgets must be a table");
+ }
+ if (!lua_isfunction(lstate, 3)) {
+ return luaL_error(lstate, "callback must be a Lua function");
+ }
+
+ bool ext_widgets[kUIGlobalCount] = { false };
+ bool tbl_has_true_val = false;
+
+ lua_pushvalue(lstate, 2);
+ lua_pushnil(lstate);
+ while (lua_next(lstate, -2)) {
+ // [dict, key, val]
+ size_t len;
+ const char *s = lua_tolstring(lstate, -2, &len);
+ bool val = lua_toboolean(lstate, -1);
+
+ for (size_t i = 0; i < kUIGlobalCount; i++) {
+ if (strequal(s, ui_ext_names[i])) {
+ if (val) {
+ tbl_has_true_val = true;
+ }
+ ext_widgets[i] = val;
+ goto ok;
+ }
+ }
+
+ return luaL_error(lstate, "Unexpected key: %s", s);
+ok:
+ lua_pop(lstate, 1);
+ }
+
+ if (!tbl_has_true_val) {
+ return luaL_error(lstate, "ext_widgets table must contain at least one 'true' value");
+ }
+
+ LuaRef ui_event_cb = nlua_ref_global(lstate, 3);
+ ui_comp_add_cb(ns_id, ui_event_cb, ext_widgets);
+ return 0;
+}
+
+/// "vim.ui_detach(ns_id)" function
+static int nlua_ui_detach(lua_State *lstate)
+ FUNC_ATTR_NONNULL_ALL
+{
+ uint32_t ns_id = (uint32_t)luaL_checkinteger(lstate, 1);
+
+ if (!ns_initialized(ns_id)) {
+ return luaL_error(lstate, "invalid ns_id");
+ }
+
+ ui_comp_remove_cb(ns_id);
+ return 0;
+}
+
/// Initialize lua interpreter state
///
/// Called by lua interpreter itself to initialize state.
@@ -649,6 +718,14 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
lua_pushcfunction(lstate, &nlua_wait);
lua_setfield(lstate, -2, "wait");
+ // ui_attach
+ lua_pushcfunction(lstate, &nlua_ui_attach);
+ lua_setfield(lstate, -2, "ui_attach");
+
+ // ui_detach
+ lua_pushcfunction(lstate, &nlua_ui_detach);
+ lua_setfield(lstate, -2, "ui_detach");
+
nlua_common_vim_init(lstate, false);
// patch require() (only for --startuptime)
@@ -967,7 +1044,7 @@ static int nlua_debug(lua_State *lstate)
if (input.v_type != VAR_STRING
|| input.vval.v_string == NULL
|| *input.vval.v_string == NUL
- || STRCMP(input.vval.v_string, "cont") == 0) {
+ || strcmp(input.vval.v_string, "cont") == 0) {
tv_clear(&input);
return 0;
}
@@ -990,7 +1067,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 +1104,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 +1170,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)) {
@@ -1348,12 +1425,11 @@ int nlua_source_using_linegetter(LineGetter fgetline, void *cookie, char *name)
/// @param[in] argcount Count of typval arguments
/// @param[in] argvars Typval Arguments
/// @param[out] rettv The return value from the called function.
-int typval_exec_lua_callable(lua_State *lstate, LuaCallable lua_cb, int argcount, typval_T *argvars,
- typval_T *rettv)
+int typval_exec_lua_callable(LuaRef lua_cb, int argcount, typval_T *argvars, typval_T *rettv)
{
- LuaRef cb = lua_cb.func_ref;
+ lua_State *lstate = global_lstate;
- nlua_pushref(lstate, cb);
+ nlua_pushref(lstate, lua_cb);
PUSH_ALL_TYPVALS(lstate, argvars, argcount, false);
@@ -1422,9 +1498,10 @@ bool nlua_ref_is_function(LuaRef ref)
/// @param name if non-NULL, sent to callback as first arg
/// if NULL, only args are used
/// @param retval if true, convert return value to Object
-/// if false, discard return value
+/// if false, only check if return value is truthy
/// @param err Error details, if any (if NULL, errors are echoed)
-/// @return Return value of function, if retval was set. Otherwise NIL.
+/// @return Return value of function, if retval was set. Otherwise
+/// BOOLEAN_OBJ(true) or NIL.
Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Error *err)
{
lua_State *const lstate = global_lstate;
@@ -1438,7 +1515,7 @@ Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Erro
nlua_push_Object(lstate, args.items[i], false);
}
- if (nlua_pcall(lstate, nargs, retval ? 1 : 0)) {
+ if (nlua_pcall(lstate, nargs, 1)) {
// if err is passed, the caller will deal with the error.
if (err) {
size_t len;
@@ -1458,7 +1535,10 @@ Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Erro
}
return nlua_pop_Object(lstate, false, err);
} else {
- return NIL;
+ bool value = lua_toboolean(lstate, -1);
+ lua_pop(lstate, 1);
+
+ return value ? BOOLEAN_OBJ(true) : NIL;
}
}
@@ -1578,7 +1658,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 +1742,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");
@@ -1749,26 +1832,6 @@ static int nlua_is_thread(lua_State *lstate)
return 1;
}
-// Required functions for lua c functions as VimL callbacks
-
-int nlua_CFunction_func_call(int argcount, typval_T *argvars, typval_T *rettv, void *state)
-{
- lua_State *const lstate = global_lstate;
- LuaCFunctionState *funcstate = (LuaCFunctionState *)state;
-
- return typval_exec_lua_callable(lstate, funcstate->lua_callable,
- argcount, argvars, rettv);
-}
-
-void nlua_CFunction_func_free(void *state)
-{
- lua_State *const lstate = global_lstate;
- LuaCFunctionState *funcstate = (LuaCFunctionState *)state;
-
- nlua_unref_global(lstate, funcstate->lua_callable.func_ref);
- xfree(funcstate);
-}
-
bool nlua_is_table_from_lua(typval_T *const arg)
{
if (arg->v_type == VAR_DICT) {
@@ -1814,11 +1877,9 @@ char_u *nlua_register_table_as_callable(typval_T *const arg)
}
lua_pop(lstate, 2); // [table]
- LuaCFunctionState *state = xmalloc(sizeof(LuaCFunctionState));
- state->lua_callable.func_ref = nlua_ref_global(lstate, -1);
+ LuaRef func = nlua_ref_global(lstate, -1);
- char_u *name = register_cfunc(&nlua_CFunction_func_call,
- &nlua_CFunction_func_free, state);
+ char_u *name = register_luafunc(func);
lua_pop(lstate, 1); // []
assert(top == lua_gettop(lstate));
@@ -1998,7 +2059,7 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview)
lua_newtable(lstate); // smods table
- lua_pushinteger(lstate, cmdmod.cmod_tab);
+ lua_pushinteger(lstate, cmdmod.cmod_tab - 1);
lua_setfield(lstate, -2, "tab");
lua_pushinteger(lstate, cmdmod.cmod_verbose - 1);
@@ -2019,6 +2080,8 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview)
lua_pushboolean(lstate, cmdmod.cmod_split & WSP_VERT);
lua_setfield(lstate, -2, "vertical");
+ lua_pushboolean(lstate, cmdmod.cmod_split & WSP_HOR);
+ lua_setfield(lstate, -2, "horizontal");
lua_pushboolean(lstate, cmdmod.cmod_flags & CMOD_SILENT);
lua_setfield(lstate, -2, "silent");
lua_pushboolean(lstate, cmdmod.cmod_flags & CMOD_ERRSILENT);
diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c
index 5a82ae30b5..9b1890403e 100644
--- a/src/nvim/lua/stdlib.c
+++ b/src/nvim/lua/stdlib.c
@@ -60,8 +60,8 @@ static int regex_match(lua_State *lstate, regprog_T **prog, char_u *str)
*prog = rm.regprog;
if (match) {
- lua_pushinteger(lstate, (lua_Integer)(rm.startp[0] - str));
- lua_pushinteger(lstate, (lua_Integer)(rm.endp[0] - str));
+ lua_pushinteger(lstate, (lua_Integer)(rm.startp[0] - (char *)str));
+ lua_pushinteger(lstate, (lua_Integer)(rm.endp[0] - (char *)str));
return 2;
}
return 0;
@@ -111,7 +111,7 @@ static int regex_match_line(lua_State *lstate)
return luaL_error(lstate, "invalid row");
}
- char_u *line = ml_get_buf(buf, rownr + 1, false);
+ char_u *line = (char_u *)ml_get_buf(buf, rownr + 1, false);
size_t len = STRLEN(line);
if (start < 0 || (size_t)start > len) {
@@ -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, (char *)from, false, (char *)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..f3c67e265f 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);
@@ -302,7 +332,7 @@ static const char *input_cb(void *payload, uint32_t byte_index, TSPoint position
*bytes_read = 0;
return "";
}
- char *line = (char *)ml_get_buf(bp, (linenr_T)position.row + 1, false);
+ char *line = ml_get_buf(bp, (linenr_T)position.row + 1, false);
size_t len = STRLEN(line);
if (position.column > len) {
*bytes_read = 0;
@@ -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;
@@ -804,7 +834,7 @@ static int node_field(lua_State *L)
do {
const char *current_field = ts_tree_cursor_current_field_name(&cursor);
- if (current_field != NULL && !STRCMP(field_name, current_field)) {
+ if (current_field != NULL && !strcmp(field_name, current_field)) {
push_node(L, ts_tree_cursor_current_node(&cursor), 1); // [table, node]
lua_rawseti(L, -2, (int)++curr_index);
}
@@ -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)
{
@@ -1195,8 +1276,8 @@ int tslua_parse_query(lua_State *L)
TSQuery *query = ts_query_new(lang, src, (uint32_t)len, &error_offset, &error_type);
if (!query) {
- return luaL_error(L, "query: %s at position %d",
- query_err_string(error_type), (int)error_offset);
+ return luaL_error(L, "query: %s at position %d for language %s",
+ query_err_string(error_type), (int)error_offset, lang_name);
}
TSQuery **ud = lua_newuserdata(L, sizeof(TSQuery *)); // [udata]
diff --git a/src/nvim/macros.h b/src/nvim/macros.h
index a896a406d1..1024ca5015 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.
@@ -54,7 +54,7 @@
#define ASCII_ISALNUM(c) (ASCII_ISALPHA(c) || ascii_isdigit(c))
// Returns empty string if it is NULL.
-#define EMPTY_IF_NULL(x) (char *)((x) ? (x) : (char_u *)"")
+#define EMPTY_IF_NULL(x) ((x) ? (x) : "")
/// Adjust chars in a language according to 'langmap' option.
/// NOTE that there is no noticeable overhead if 'langmap' is not set.
@@ -104,7 +104,7 @@
// MB_PTR_BACK(): backup a pointer to the previous character, taking care of
// multi-byte characters if needed. Only use with "p" > "s" !
#define MB_PTR_BACK(s, p) \
- (p -= utf_head_off((char_u *)(s), (char_u *)(p) - 1) + 1)
+ (p -= utf_head_off((char *)(s), (char *)(p) - 1) + 1)
// MB_CHAR2BYTES(): convert character to bytes and advance pointer to bytes
#define MB_CHAR2BYTES(c, b) ((b) += utf_char2bytes((c), ((char *)b)))
diff --git a/src/nvim/main.c b/src/nvim/main.c
index d06b475934..a73c465042 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;
@@ -1416,10 +1390,9 @@ scripterror:
TIME_MSG("parsing arguments");
}
-/*
- * Many variables are in "params" so that we can pass them to invoked
- * functions without a lot of arguments. "argc" and "argv" are also
- * copied, so that they can be changed. */
+// Many variables are in "params" so that we can pass them to invoked
+// functions without a lot of arguments. "argc" and "argv" are also
+// copied, so that they can be changed.
static void init_params(mparm_T *paramp, int argc, char **argv)
{
CLEAR_POINTER(paramp);
@@ -1491,9 +1464,7 @@ static char_u *get_fname(mparm_T *parmp, char_u *cwd)
return (char_u *)alist_name(&GARGLIST[0]);
}
-/*
- * Decide about window layout for diff mode after reading vimrc.
- */
+// Decide about window layout for diff mode after reading vimrc.
static void set_window_layout(mparm_T *paramp)
{
if (paramp->diff_mode && paramp->window_layout == 0) {
@@ -1505,10 +1476,8 @@ static void set_window_layout(mparm_T *paramp)
}
}
-/*
- * "-q errorfile": Load the error file now.
- * If the error file can't be read, exit before doing anything else.
- */
+// "-q errorfile": Load the error file now.
+// If the error file can't be read, exit before doing anything else.
static void handle_quickfix(mparm_T *paramp)
{
if (paramp->edit_type == EDIT_QF) {
@@ -1516,7 +1485,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);
}
@@ -1524,10 +1493,8 @@ static void handle_quickfix(mparm_T *paramp)
}
}
-/*
- * Need to jump to the tag before executing the '-c command'.
- * Makes "vim -c '/return' -t main" work.
- */
+// Need to jump to the tag before executing the '-c command'.
+// Makes "vim -c '/return' -t main" work.
static void handle_tag(char_u *tagname)
{
if (tagname != NULL) {
@@ -1566,18 +1533,14 @@ static void read_stdin(void)
check_swap_exists_action();
}
-/*
- * Create the requested number of windows and edit buffers in them.
- * Also does recovery if "recoverymode" set.
- */
+// Create the requested number of windows and edit buffers in them.
+// Also does recovery if "recoverymode" set.
static void create_windows(mparm_T *parmp)
{
int dorewind;
int done = 0;
- /*
- * Create the number of windows that was requested.
- */
+ // Create the number of windows that was requested.
if (parmp->window_count == -1) { // was not set
parmp->window_count = 1;
}
@@ -1638,7 +1601,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 +1610,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 +1630,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) {
@@ -1696,9 +1659,7 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd)
win_T *win;
char *p_shm_save = NULL;
- /*
- * Don't execute Win/Buf Enter/Leave autocommands here
- */
+ // Don't execute Win/Buf Enter/Leave autocommands here
autocmd_no_enter++;
autocmd_no_leave++;
@@ -1709,7 +1670,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 +1694,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 +1721,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 +1740,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);
}
@@ -1807,9 +1768,7 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd)
}
}
-/*
- * Execute the commands from --cmd arguments "cmds[cnt]".
- */
+// Execute the commands from --cmd arguments "cmds[cnt]".
static void exe_pre_commands(mparm_T *parmp)
{
char **cmds = parmp->pre_commands;
@@ -1829,19 +1788,15 @@ static void exe_pre_commands(mparm_T *parmp)
}
}
-/*
- * Execute "+", "-c" and "-S" arguments.
- */
+// Execute "+", "-c" and "-S" arguments.
static void exe_commands(mparm_T *parmp)
{
int i;
- /*
- * We start commands on line 0, make "vim +/pat file" match a
- * pattern on line 1. But don't move the cursor when an autocommand
- * with g`" was used.
- */
- msg_scroll = TRUE;
+ // We start commands on line 0, make "vim +/pat file" match a
+ // pattern on line 1. But don't move the cursor when an autocommand
+ // with g`" was used.
+ msg_scroll = true;
if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1) {
curwin->w_cursor.lnum = 0;
}
@@ -1861,12 +1816,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");
}
@@ -1940,9 +1895,9 @@ static bool do_user_initialization(void)
char_u *user_vimrc = (char_u *)stdpaths_user_conf_subpath("init.vim");
// init.lua
- if (os_path_exists(init_lua_path)
+ if (os_path_exists((char *)init_lua_path)
&& do_source((char *)init_lua_path, true, DOSO_VIMRC)) {
- if (os_path_exists(user_vimrc)) {
+ if (os_path_exists((char *)user_vimrc)) {
semsg(_("E5422: Conflicting configs: \"%s\" \"%s\""), init_lua_path,
user_vimrc);
}
@@ -2163,11 +2118,9 @@ static void usage(void)
mch_msg(_("\nSee \":help startup-options\" for all options.\n"));
}
-/*
- * Check the result of the ATTENTION dialog:
- * When "Quit" selected, exit Vim.
- * When "Recover" selected, recover the file.
- */
+// Check the result of the ATTENTION dialog:
+// When "Quit" selected, exit Vim.
+// When "Recover" selected, recover the file.
static void check_swap_exists_action(void)
{
if (swap_exists_action == SEA_QUIT) {
diff --git a/src/nvim/map.c b/src/nvim/map.c
index d3058a5d52..3e449d2eb1 100644
--- a/src/nvim/map.c
+++ b/src/nvim/map.c
@@ -163,11 +163,14 @@ static inline bool ColorKey_eq(ColorKey ae1, ColorKey ae2)
return memcmp(&ae1, &ae2, sizeof(ae1)) == 0;
}
+MAP_IMPL(int, ptr_t, DEFAULT_INITIALIZER)
+MAP_IMPL(ptr_t, int, DEFAULT_INITIALIZER)
MAP_IMPL(int, int, DEFAULT_INITIALIZER)
MAP_IMPL(int, cstr_t, DEFAULT_INITIALIZER)
MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(cstr_t, int, DEFAULT_INITIALIZER)
MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER)
+MAP_IMPL(uint32_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(uint64_t, ssize_t, SSIZE_INITIALIZER)
MAP_IMPL(uint64_t, uint64_t, DEFAULT_INITIALIZER)
diff --git a/src/nvim/map.h b/src/nvim/map.h
index 845daac3f7..2e18225731 100644
--- a/src/nvim/map.h
+++ b/src/nvim/map.h
@@ -34,11 +34,14 @@
//
// NOTE: Keys AND values must be allocated! khash.h does not make a copy.
//
+MAP_DECLS(int, ptr_t)
MAP_DECLS(int, int)
+MAP_DECLS(ptr_t, int)
MAP_DECLS(int, cstr_t)
MAP_DECLS(cstr_t, ptr_t)
MAP_DECLS(cstr_t, int)
MAP_DECLS(ptr_t, ptr_t)
+MAP_DECLS(uint32_t, ptr_t)
MAP_DECLS(uint64_t, ptr_t)
MAP_DECLS(uint64_t, ssize_t)
MAP_DECLS(uint64_t, uint64_t)
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 64a798a27b..9f169427f5 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;
}
@@ -174,7 +174,7 @@ static void showmap(mapblock_T *mp, bool local)
}
// Display the LHS. Get length of what we write.
- len = (size_t)msg_outtrans_special(mp->m_keys, true, 0);
+ len = (size_t)msg_outtrans_special((char *)mp->m_keys, true, 0);
do {
msg_putchar(' '); // padd with blanks
len++;
@@ -214,7 +214,6 @@ static void showmap(mapblock_T *mp, bool local)
last_set_msg(mp->m_script_ctx);
}
msg_clr_eos();
- ui_flush(); // show one line at a time
}
/// Replace termcodes in the given LHS and RHS and store the results into the
@@ -277,26 +276,34 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs
mapargs->alt_lhs_len = 0;
}
+ set_maparg_rhs(orig_rhs, orig_rhs_len, rhs_lua, cpo_flags, mapargs);
+
+ return true;
+}
+
+/// @see set_maparg_lhs_rhs
+static void set_maparg_rhs(const char *const orig_rhs, const size_t orig_rhs_len,
+ const LuaRef rhs_lua, const int cpo_flags, MapArguments *const mapargs)
+{
mapargs->rhs_lua = rhs_lua;
if (rhs_lua == LUA_NOREF) {
mapargs->orig_rhs_len = orig_rhs_len;
mapargs->orig_rhs = xcalloc(mapargs->orig_rhs_len + 1, sizeof(char_u));
STRLCPY(mapargs->orig_rhs, orig_rhs, mapargs->orig_rhs_len + 1);
-
if (STRICMP(orig_rhs, "<nop>") == 0) { // "<Nop>" means nothing
- mapargs->rhs = xcalloc(1, sizeof(char_u)); // single null-char
+ mapargs->rhs = xcalloc(1, sizeof(char_u)); // single NUL-char
mapargs->rhs_len = 0;
mapargs->rhs_is_noop = true;
} else {
char *rhs_buf = NULL;
- replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, REPTERM_DO_LT, NULL,
- cpo_flags);
+ char *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;
+ mapargs->rhs = replaced;
}
} else {
char tmp_buf[64];
@@ -306,9 +313,8 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs
// stores <lua>ref_no<cr> in map_str
mapargs->rhs_len = (size_t)vim_snprintf(S_LEN(tmp_buf), "%c%c%c%d\r", K_SPECIAL,
(char_u)KS_EXTRA, KE_LUA, rhs_lua);
- mapargs->rhs = vim_strsave((char_u *)tmp_buf);
+ mapargs->rhs = xstrdup(tmp_buf);
}
- return true;
}
/// Parse a string of |:map-arguments| into a @ref MapArguments struct.
@@ -433,7 +439,7 @@ static int str_to_mapargs(const char_u *strargs, bool is_unmap, MapArguments *ma
/// and "desc" fields are used.
/// "rhs", "rhs_lua", "orig_rhs" fields are cleared if "simplified" is false.
/// @param sid -1 to use current_sctx
-static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table, const char_u *keys,
+static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table, const char *keys,
MapArguments *args, int noremap, int mode, bool is_abbr, scid_T sid,
linenr_T lnum, bool simplified)
{
@@ -448,9 +454,9 @@ static void map_add(buf_T *buf, mapblock_T **map_table, mapblock_T **abbr_table,
}
}
- mp->m_keys = vim_strsave(keys);
+ mp->m_keys = (uint8_t *)xstrdup(keys);
mp->m_str = args->rhs;
- mp->m_orig_str = args->orig_rhs;
+ mp->m_orig_str = (char *)args->orig_rhs;
mp->m_luaref = args->rhs_lua;
if (!simplified) {
args->rhs = NULL;
@@ -704,7 +710,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;
@@ -762,7 +768,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
XFREE_CLEAR(mp->m_orig_str);
}
mp->m_str = args->rhs;
- mp->m_orig_str = args->orig_rhs;
+ mp->m_orig_str = (char *)args->orig_rhs;
mp->m_luaref = args->rhs_lua;
if (!keyround1_simplified) {
args->rhs = NULL;
@@ -840,7 +846,7 @@ static int buf_do_map(int maptype, MapArguments *args, int mode, bool is_abbrev,
}
// Get here when adding a new entry to the maphash[] list or abbrlist.
- map_add(buf, map_table, abbr_table, lhs, args, noremap, mode, is_abbrev,
+ map_add(buf, map_table, abbr_table, (char *)lhs, args, noremap, mode, is_abbrev,
-1, // sid
0, // lnum
keyround1_simplified);
@@ -965,12 +971,12 @@ static int get_map_mode(char **cmdp, bool forceit)
/// Clear all mappings (":mapclear") or abbreviations (":abclear").
/// "abbr" should be false for mappings, true for abbreviations.
/// This function used to be called map_clear().
-static void do_mapclear(char *cmdp, char_u *arg, int forceit, int abbr)
+static void do_mapclear(char *cmdp, char *arg, int forceit, int abbr)
{
int mode;
int local;
- local = (STRCMP(arg, "<buffer>") == 0);
+ local = (strcmp(arg, "<buffer>") == 0);
if (!local && *arg != NUL) {
emsg(_(e_invarg));
return;
@@ -1113,7 +1119,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;
}
}
@@ -1259,7 +1265,7 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char ***file)
int hash;
int count;
int round;
- char_u *p;
+ char *p;
int i;
*num_file = 0; // return values in case of FAIL
@@ -1272,28 +1278,28 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char ***file)
for (i = 0; i < 7; i++) {
if (i == 0) {
- p = (char_u *)"<silent>";
+ p = "<silent>";
} else if (i == 1) {
- p = (char_u *)"<unique>";
+ p = "<unique>";
} else if (i == 2) {
- p = (char_u *)"<script>";
+ p = "<script>";
} else if (i == 3) {
- p = (char_u *)"<expr>";
+ p = "<expr>";
} else if (i == 4 && !expand_buffer) {
- p = (char_u *)"<buffer>";
+ p = "<buffer>";
} else if (i == 5) {
- p = (char_u *)"<nowait>";
+ p = "<nowait>";
} else if (i == 6) {
- p = (char_u *)"<special>";
+ p = "<special>";
} else {
continue;
}
- if (vim_regexec(regmatch, (char *)p, (colnr_T)0)) {
+ if (vim_regexec(regmatch, p, (colnr_T)0)) {
if (round == 1) {
count++;
} else {
- (*file)[count++] = (char *)vim_strsave(p);
+ (*file)[count++] = xstrdup(p);
}
}
}
@@ -1311,12 +1317,12 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char ***file)
}
for (; mp; mp = mp->m_next) {
if (mp->m_mode & expand_mapmodes) {
- p = translate_mapping(mp->m_keys, CPO_TO_CPO_FLAGS);
- if (p != NULL && vim_regexec(regmatch, (char *)p, (colnr_T)0)) {
+ p = (char *)translate_mapping(mp->m_keys, CPO_TO_CPO_FLAGS);
+ if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0)) {
if (round == 1) {
count++;
} else {
- (*file)[count++] = (char *)p;
+ (*file)[count++] = p;
p = NULL;
}
}
@@ -1344,7 +1350,7 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char ***file)
char **ptr3 = ptr1 + count;
while (ptr2 < ptr3) {
- if (STRCMP(*ptr1, *ptr2)) {
+ if (strcmp(*ptr1, *ptr2)) {
*++ptr1 = *ptr2++;
} else {
xfree(*ptr2++);
@@ -1441,20 +1447,20 @@ bool check_abbr(int c, char_u *ptr, int col, int mincol)
mp->m_next == NULL ? (mp = mp2, mp2 = NULL) :
(mp = mp->m_next)) {
int qlen = mp->m_keylen;
- char_u *q = mp->m_keys;
+ char *q = (char *)mp->m_keys;
int match;
if (strchr((const char *)mp->m_keys, K_SPECIAL) != NULL) {
// Might have K_SPECIAL escaped mp->m_keys.
- q = vim_strsave(mp->m_keys);
- vim_unescape_ks(q);
+ q = xstrdup((char *)mp->m_keys);
+ vim_unescape_ks((char_u *)q);
qlen = (int)STRLEN(q);
}
// find entries with right mode and keys
match = (mp->m_mode & State)
&& qlen == len
&& !STRNCMP(q, ptr, (size_t)len);
- if (q != mp->m_keys) {
+ if (q != (char *)mp->m_keys) {
xfree(q);
}
if (match) {
@@ -1504,9 +1510,9 @@ bool check_abbr(int c, char_u *ptr, int col, int mincol)
(void)ins_typebuf((char *)tb, 1, 0, true, mp->m_silent);
}
if (mp->m_expr) {
- s = eval_map_expr(mp, c);
+ s = (char_u *)eval_map_expr(mp, c);
} else {
- s = mp->m_str;
+ s = (char_u *)mp->m_str;
}
if (s != NULL) {
// insert the to string
@@ -1534,16 +1540,16 @@ bool check_abbr(int c, char_u *ptr, int col, int mincol)
/// special characters.
///
/// @param c NUL or typed character for abbreviation
-char_u *eval_map_expr(mapblock_T *mp, int c)
+char *eval_map_expr(mapblock_T *mp, int c)
{
- char_u *p = NULL;
- char_u *expr = NULL;
+ char *p = NULL;
+ char *expr = NULL;
// 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);
- vim_unescape_ks(expr);
+ expr = xstrdup(mp->m_str);
+ vim_unescape_ks((char_u *)expr);
}
// Forbid changing text or using ":normal" to avoid most of the bad side
@@ -1559,7 +1565,7 @@ char_u *eval_map_expr(mapblock_T *mp, int c)
Array args = ARRAY_DICT_INIT;
Object ret = nlua_call_ref(mp->m_luaref, NULL, args, true, &err);
if (ret.type == kObjectTypeString) {
- p = (char_u *)xstrndup(ret.data.string.data, ret.data.string.size);
+ p = xstrndup(ret.data.string.data, ret.data.string.size);
}
api_free_object(ret);
if (err.type != kErrorTypeNone) {
@@ -1567,7 +1573,7 @@ char_u *eval_map_expr(mapblock_T *mp, int c)
api_clear_error(&err);
}
} else {
- p = (char_u *)eval_to_string((char *)expr, NULL, false);
+ p = eval_to_string(expr, NULL, false);
xfree(expr);
}
textlock--;
@@ -1580,13 +1586,13 @@ char_u *eval_map_expr(mapblock_T *mp, int c)
return NULL;
}
- char_u *res = NULL;
+ char *res = NULL;
if (mp->m_replace_keycodes) {
- replace_termcodes((char *)p, STRLEN(p), (char **)&res, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS);
+ replace_termcodes(p, STRLEN(p), &res, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS);
} else {
// Escape K_SPECIAL in the result to be able to use the string as typeahead.
- res = (char_u *)vim_strsave_escape_ks((char *)p);
+ res = vim_strsave_escape_ks(p);
}
xfree(p);
@@ -1639,7 +1645,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 +1791,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 +1962,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 +1973,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]);
@@ -1989,18 +1995,19 @@ void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/// Fill a dictionary with all applicable maparg() like dictionaries
+/// Fill a Dictionary with all applicable maparg() like dictionaries
///
-/// @param dict The dictionary to be filled
/// @param mp The maphash that contains the mapping information
/// @param buffer_value The "buffer" value
/// @param compatible True for compatible with old maparg() dict
-static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp,
- const char *lhsrawalt, long buffer_value, bool compatible)
- FUNC_ATTR_NONNULL_ARG(1, 2)
+///
+/// @return A Dictionary.
+static Dictionary mapblock_fill_dict(const mapblock_T *const mp, const char *lhsrawalt,
+ const long buffer_value, const bool compatible)
+ FUNC_ATTR_NONNULL_ARG(1)
{
- char *const lhs = str2special_save((const char *)mp->m_keys,
- compatible, !compatible);
+ Dictionary dict = ARRAY_DICT_INIT;
+ char *const lhs = str2special_save((const char *)mp->m_keys, compatible, !compatible);
char *const mapmode = map_mode_to_chars(mp->m_mode);
varnumber_T noremap_value;
@@ -2015,37 +2022,35 @@ static void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp,
}
if (mp->m_luaref != LUA_NOREF) {
- tv_dict_add_nr(dict, S_LEN("callback"), mp->m_luaref);
+ PUT(dict, "callback", LUAREF_OBJ(api_new_luaref(mp->m_luaref)));
} else {
- if (compatible) {
- tv_dict_add_str(dict, S_LEN("rhs"), (const char *)mp->m_orig_str);
- } else {
- tv_dict_add_allocated_str(dict, S_LEN("rhs"),
- str2special_save((const char *)mp->m_str, false,
- true));
- }
+ PUT(dict, "rhs", STRING_OBJ(compatible
+ ? cstr_to_string(mp->m_orig_str)
+ : cstr_as_string(str2special_save(mp->m_str, false, true))));
}
if (mp->m_desc != NULL) {
- tv_dict_add_allocated_str(dict, S_LEN("desc"), xstrdup(mp->m_desc));
+ PUT(dict, "desc", STRING_OBJ(cstr_to_string(mp->m_desc)));
}
- tv_dict_add_allocated_str(dict, S_LEN("lhs"), lhs);
- tv_dict_add_str(dict, S_LEN("lhsraw"), (const char *)mp->m_keys);
+ PUT(dict, "lhs", STRING_OBJ(cstr_as_string(lhs)));
+ PUT(dict, "lhsraw", STRING_OBJ(cstr_to_string((const char *)mp->m_keys)));
if (lhsrawalt != NULL) {
// Also add the value for the simplified entry.
- tv_dict_add_str(dict, S_LEN("lhsrawalt"), lhsrawalt);
- }
- tv_dict_add_nr(dict, S_LEN("noremap"), noremap_value);
- tv_dict_add_nr(dict, S_LEN("script"), mp->m_noremap == REMAP_SCRIPT ? 1 : 0);
- tv_dict_add_nr(dict, S_LEN("expr"), mp->m_expr ? 1 : 0);
- tv_dict_add_nr(dict, S_LEN("silent"), mp->m_silent ? 1 : 0);
- tv_dict_add_nr(dict, S_LEN("sid"), (varnumber_T)mp->m_script_ctx.sc_sid);
- tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)mp->m_script_ctx.sc_lnum);
- tv_dict_add_nr(dict, S_LEN("buffer"), (varnumber_T)buffer_value);
- tv_dict_add_nr(dict, S_LEN("nowait"), mp->m_nowait ? 1 : 0);
+ PUT(dict, "lhsrawalt", STRING_OBJ(cstr_to_string(lhsrawalt)));
+ }
+ PUT(dict, "noremap", INTEGER_OBJ(noremap_value));
+ PUT(dict, "script", INTEGER_OBJ(mp->m_noremap == REMAP_SCRIPT ? 1 : 0));
+ PUT(dict, "expr", INTEGER_OBJ(mp->m_expr ? 1 : 0));
+ PUT(dict, "silent", INTEGER_OBJ(mp->m_silent ? 1 : 0));
+ PUT(dict, "sid", INTEGER_OBJ((varnumber_T)mp->m_script_ctx.sc_sid));
+ PUT(dict, "lnum", INTEGER_OBJ((varnumber_T)mp->m_script_ctx.sc_lnum));
+ PUT(dict, "buffer", INTEGER_OBJ((varnumber_T)buffer_value));
+ PUT(dict, "nowait", INTEGER_OBJ(mp->m_nowait ? 1 : 0));
if (mp->m_replace_keycodes) {
- tv_dict_add_nr(dict, S_LEN("replace_keycodes"), 1);
+ PUT(dict, "replace_keycodes", INTEGER_OBJ(1));
}
- tv_dict_add_allocated_str(dict, S_LEN("mode"), mapmode);
+ PUT(dict, "mode", STRING_OBJ(cstr_as_string(mapmode)));
+
+ return dict;
}
static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
@@ -2114,11 +2119,16 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
rettv->vval.v_string = nlua_funcref_str(mp->m_luaref);
}
} else {
- tv_dict_alloc_ret(rettv);
+ // Return a dictionary.
if (mp != NULL && (rhs != NULL || rhs_lua != LUA_NOREF)) {
- // Return a dictionary.
- mapblock_fill_dict(rettv->vval.v_dict, mp, did_simplify ? (char *)keys_simplified : NULL,
- buffer_local, true);
+ Dictionary dict = mapblock_fill_dict(mp,
+ did_simplify ? (char *)keys_simplified : NULL,
+ buffer_local, true);
+ (void)object_to_vim(DICTIONARY_OBJ(dict), rettv, NULL);
+ api_free_dictionary(dict);
+ } else {
+ // Return an empty dictionary.
+ tv_dict_alloc_ret(rettv);
}
}
@@ -2127,7 +2137,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);
@@ -2147,29 +2157,36 @@ void f_mapset(typval_T *argvars, typval_T *rettv, FunPtr fptr)
char *lhs = tv_dict_get_string(d, "lhs", false);
char *lhsraw = tv_dict_get_string(d, "lhsraw", false);
char *lhsrawalt = tv_dict_get_string(d, "lhsrawalt", false);
- char *rhs = tv_dict_get_string(d, "rhs", false);
- if (lhs == NULL || lhsraw == NULL || rhs == NULL) {
+ char *orig_rhs = tv_dict_get_string(d, "rhs", false);
+ LuaRef rhs_lua = LUA_NOREF;
+ dictitem_T *callback_di = tv_dict_find(d, S_LEN("callback"));
+ if (callback_di != NULL) {
+ Object callback_obj = vim_to_object(&callback_di->di_tv);
+ if (callback_obj.type == kObjectTypeLuaRef && callback_obj.data.luaref != LUA_NOREF) {
+ rhs_lua = callback_obj.data.luaref;
+ orig_rhs = "";
+ callback_obj.data.luaref = LUA_NOREF;
+ }
+ api_free_object(callback_obj);
+ }
+ if (lhs == NULL || lhsraw == NULL || orig_rhs == NULL) {
emsg(_("E460: entries missing in mapset() dict argument"));
+ api_free_luaref(rhs_lua);
return;
}
- char *orig_rhs = rhs;
- char *arg_buf = NULL;
- rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS);
- int noremap = tv_dict_get_number(d, "noremap") ? REMAP_NONE : 0;
+ int noremap = tv_dict_get_number(d, "noremap") != 0 ? REMAP_NONE : 0;
if (tv_dict_get_number(d, "script") != 0) {
noremap = REMAP_SCRIPT;
}
- MapArguments args = { // TODO(zeertzjq): support restoring "callback"?
- .rhs = (char_u *)rhs,
- .rhs_lua = LUA_NOREF,
- .orig_rhs = vim_strsave((char_u *)orig_rhs),
+ MapArguments args = {
.expr = tv_dict_get_number(d, "expr") != 0,
.silent = tv_dict_get_number(d, "silent") != 0,
.nowait = tv_dict_get_number(d, "nowait") != 0,
.replace_keycodes = tv_dict_get_number(d, "replace_keycodes") != 0,
.desc = tv_dict_get_string(d, "desc", false),
};
+ set_maparg_rhs(orig_rhs, strlen(orig_rhs), rhs_lua, CPO_TO_CPO_FLAGS, &args);
scid_T sid = (scid_T)tv_dict_get_number(d, "sid");
linenr_T lnum = (linenr_T)tv_dict_get_number(d, "lnum");
bool buffer = tv_dict_get_number(d, "buffer") != 0;
@@ -2180,28 +2197,28 @@ void f_mapset(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Delete any existing mapping for this lhs and mode.
MapArguments unmap_args = MAP_ARGUMENTS_INIT;
- set_maparg_lhs_rhs(lhs, strlen(lhs), rhs, strlen(rhs), LUA_NOREF, 0, &unmap_args);
+ set_maparg_lhs_rhs(lhs, strlen(lhs), "", 0, LUA_NOREF, 0, &unmap_args);
unmap_args.buffer = buffer;
buf_do_map(MAPTYPE_UNMAP, &unmap_args, mode, false, curbuf);
xfree(unmap_args.rhs);
xfree(unmap_args.orig_rhs);
if (lhsrawalt != NULL) {
- map_add(curbuf, map_table, abbr_table, (char_u *)lhsrawalt, &args, noremap, mode, is_abbr,
+ map_add(curbuf, map_table, abbr_table, lhsrawalt, &args, noremap, mode, is_abbr,
sid, lnum, true);
}
- map_add(curbuf, map_table, abbr_table, (char_u *)lhsraw, &args, noremap, mode, is_abbr,
+ map_add(curbuf, map_table, abbr_table, lhsraw, &args, noremap, mode, is_abbr,
sid, lnum, false);
}
/// "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 +2339,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) {
@@ -2440,13 +2457,13 @@ void ex_unmap(exarg_T *eap)
/// ":mapclear" and friends.
void ex_mapclear(exarg_T *eap)
{
- do_mapclear(eap->cmd, (char_u *)eap->arg, eap->forceit, false);
+ do_mapclear(eap->cmd, eap->arg, eap->forceit, false);
}
/// ":abclear" and friends.
void ex_abclear(exarg_T *eap)
{
- do_mapclear(eap->cmd, (char_u *)eap->arg, true, true);
+ do_mapclear(eap->cmd, eap->arg, true, true);
}
/// Set, tweak, or remove a mapping in a mode. Acts as the implementation for
@@ -2599,12 +2616,10 @@ fail_and_free:
///
/// @param mode The abbreviation for the mode
/// @param buf The buffer to get the mapping array. NULL for global
-/// @param from_lua Whether it is called from internal Lua api.
/// @returns Array of maparg()-like dictionaries describing mappings
-ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, bool from_lua)
+ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf)
{
Array mappings = ARRAY_DICT_INIT;
- dict_T *const dict = tv_dict_alloc();
// Convert the string mode to the integer mode
// that is stored within each mapblock
@@ -2623,25 +2638,11 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, bool from_lua)
}
// Check for correct mode
if (int_mode & current_maphash->m_mode) {
- mapblock_fill_dict(dict, current_maphash, NULL, buffer_value, false);
- Object api_dict = vim_to_object((typval_T[]) { { .v_type = VAR_DICT,
- .vval.v_dict = dict } });
- if (from_lua) {
- Dictionary d = api_dict.data.dictionary;
- for (size_t j = 0; j < d.size; j++) {
- if (strequal("callback", d.items[j].key.data)) {
- d.items[j].value.type = kObjectTypeLuaRef;
- d.items[j].value.data.luaref = api_new_luaref((LuaRef)d.items[j].value.data.integer);
- break;
- }
- }
- }
- ADD(mappings, api_dict);
- tv_dict_clear(dict);
+ ADD(mappings,
+ DICTIONARY_OBJ(mapblock_fill_dict(current_maphash, NULL, buffer_value, false)));
}
}
}
- tv_dict_free(dict);
return mappings;
}
diff --git a/src/nvim/mapping.h b/src/nvim/mapping.h
index 7c48c3bce2..182d1a48cb 100644
--- a/src/nvim/mapping.h
+++ b/src/nvim/mapping.h
@@ -35,7 +35,7 @@ struct map_arguments {
char_u alt_lhs[MAXMAPLEN + 1];
size_t alt_lhs_len;
- char_u *rhs; /// The {rhs} of the mapping.
+ char *rhs; /// The {rhs} of the mapping.
size_t rhs_len;
LuaRef rhs_lua; /// lua function as {rhs}
bool rhs_is_noop; /// True when the {rhs} should be <Nop>.
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 593275d489..049a3cb50b 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -1,9 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * mark.c: functions for setting marks and jumping to them
- */
+// mark.c: functions for setting marks and jumping to them
#include <assert.h>
#include <inttypes.h>
@@ -17,10 +15,12 @@
#include "nvim/diff.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
+#include "nvim/eval/typval.h"
#include "nvim/ex_cmds.h"
#include "nvim/extmark.h"
#include "nvim/fold.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
@@ -33,34 +33,57 @@
#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"
+#include "nvim/map.h"
+#include "nvim/eval/userfunc.h"
-/*
- * This file contains routines to maintain and manipulate marks.
- */
+// This file contains routines to maintain and manipulate marks.
-/*
- * If a named file mark's lnum is non-zero, it is valid.
- * If a named file mark's fnum is non-zero, it is for an existing buffer,
- * otherwise it is from .shada and namedfm[n].fname is the file name.
- * There are marks 'A - 'Z (set by user) and '0 to '9 (set when writing
- * shada).
- */
+// If a named file mark's lnum is non-zero, it is valid.
+// If a named file mark's fnum is non-zero, it is for an existing buffer,
+// otherwise it is from .shada and namedfm[n].fname is the file name.
+// There are marks 'A - 'Z (set by user) and '0 to '9 (set when writing
+// shada).
/// Global marks (marks with file number or name)
static xfmark_T namedfm[NGLOBALMARKS];
+static struct {
+ Map(int, ptr_t) named;
+} usermarks;
+bool usermarks_init;
+
+static xfmark_T* lookup_user_mark(int mark)
+{
+ if (!usermarks_init) {
+ map_init(int, ptr_t, &usermarks.named);
+ usermarks_init = 1;
+ }
+
+ xfmark_T **ret =
+ (xfmark_T**) map_ref(int, ptr_t)(&usermarks.named, mark, true);
+
+ if (ret) {
+ if (! (*ret)) {
+ *ret = xcalloc(sizeof(xfmark_T), 1);
+ }
+
+ return *ret;
+ }
+
+ return NULL;
+}
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "mark.c.generated.h"
#endif
-/*
- * Set named mark "c" at current cursor position.
- * Returns OK on success, FAIL if bad name given.
- */
+
+// Set named mark "c" at current cursor position.
+// Returns OK on success, FAIL if bad name given.
int setmark(int c)
{
fmarkv_T view = mark_view_make(curwin->w_topline, curwin->w_cursor);
@@ -88,11 +111,9 @@ void clear_fmark(fmark_T *fm)
CLEAR_POINTER(fm);
}
-/*
- * Set named mark "c" to position "pos".
- * When "c" is upper case use file "fnum".
- * Returns OK on success, FAIL if bad name given.
- */
+// Set named mark "c" to position "pos".
+// When "c" is upper case use file "fnum".
+// Returns OK on success, FAIL if bad name given.
int setmark_pos(int c, pos_T *pos, int fnum, fmarkv_T *view_pt)
{
int i;
@@ -163,13 +184,12 @@ int setmark_pos(int c, pos_T *pos, int fnum, fmarkv_T *view_pt)
RESET_XFMARK(namedfm + i, *pos, fnum, view, NULL);
return OK;
}
- return FAIL;
+
+ return mark_set_user(buf, c);
}
-/*
- * Set the previous context mark to the current position and add it to the
- * jump list.
- */
+// Set the previous context mark to the current position and add it to the
+// jump list.
void setpcmark(void)
{
xfmark_T *fm;
@@ -210,12 +230,10 @@ void setpcmark(void)
SET_XFMARK(fm, curwin->w_pcmark, curbuf->b_fnum, view, NULL);
}
-/*
- * To change context, call setpcmark(), then move the current position to
- * where ever, then call checkpcmark(). This ensures that the previous
- * context will only be changed if the cursor moved to a different line.
- * If pcmark was deleted (with "dG") the previous mark is restored.
- */
+// To change context, call setpcmark(), then move the current position to
+// where ever, then call checkpcmark(). This ensures that the previous
+// context will only be changed if the cursor moved to a different line.
+// If pcmark was deleted (with "dG") the previous mark is restored.
void checkpcmark(void)
{
if (curwin->w_prev_pcmark.lnum != 0
@@ -348,6 +366,15 @@ fmark_T *mark_get(buf_T *buf, win_T *win, fmark_T *fmp, MarkGet flag, int name)
// Local Marks
fm = mark_get_local(buf, win, name);
}
+
+ if (!fm) {
+ // Get usermark.
+ xfmark_T* xm = mark_get_user(buf, name);
+ if (xm) {
+ fm = &xm->fmark;
+ }
+ }
+
if (fmp != NULL && fm != NULL) {
*fmp = *fm;
return fmp;
@@ -436,6 +463,123 @@ fmark_T *mark_get_local(buf_T *buf, win_T *win, int name)
return mark;
}
+/// Loads the mark 'out' with the results from calling the usermarkfunc.
+///
+/// @param umf String for the usermarkfunc
+/// @param name name for the mark
+/// @param[out] out the mark to write the results to.
+static int call_umf(
+ const char* umf, int name, typval_T* out, const char* get_or_set_a)
+{
+ char markname_str[5];
+ char get_or_set[4];
+ int len;
+
+ strncpy(get_or_set, get_or_set_a, sizeof(get_or_set));
+ get_or_set[3] = 0;
+
+ len = (*utf_char2len)(name);
+ markname_str[len] = 0;
+ utf_char2bytes(name, markname_str);
+
+ typval_T args[3];
+ args[0].v_type = VAR_STRING;
+ args[1].v_type = VAR_STRING;
+ args[2].v_type = VAR_UNKNOWN;
+
+ args[0].vval.v_string = get_or_set;
+ args[1].vval.v_string = markname_str;
+
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.evaluate = true;
+
+ return call_func(umf, -1, out, 2, args, &funcexe);
+}
+
+static int typval_to_xfmark(buf_T* buf, xfmark_T* out, typval_T* in)
+{
+ varnumber_T line;
+ varnumber_T col;
+ char* filename = NULL;
+
+ switch (in->v_type) {
+ case VAR_DICT:
+ line = tv_dict_get_number(in->vval.v_dict, "line");
+ col = tv_dict_get_number(in->vval.v_dict, "col");
+ filename = tv_dict_get_string(in->vval.v_dict, "file", true);
+ break;
+
+ case VAR_NUMBER:
+ line = in->vval.v_number;
+ col = 1;
+ break;
+
+ default:
+ return -1;
+ }
+
+ free_xfmark(*out);
+ memset(out, 0, sizeof(*out));
+
+ out->fname = filename;
+ out->fmark.mark.col = (int) col;
+ out->fmark.mark.lnum = (int) line;
+ out->fmark.fnum = 0;
+ out->fmark.timestamp = os_time();
+
+ return 0;
+}
+
+/// Gets marks that are defined by the user.
+///
+/// @param buf the buffer
+/// @param name name fo the mark
+xfmark_T *mark_get_user(buf_T* buf, int name)
+{
+ const char* umf = (const char*) buf->b_p_umf;
+
+ if (!umf) {
+ return NULL;
+ }
+
+ xfmark_T* mark = lookup_user_mark(name);
+ if (mark) {
+ typval_T* typval = xcalloc(sizeof(typval_T), 1);
+ call_umf(umf, name, typval, "get");
+ typval_to_xfmark(buf, mark, typval);
+ tv_free(typval);
+
+ if (mark->fname) {
+ buf_T* buffer =
+ buflist_new(
+ mark->fname, NULL, mark->fmark.mark.lnum, BLN_CURBUF | BLN_LISTED);
+
+ if (buffer) {
+ mark->fmark.fnum = buffer->b_fnum;
+ }
+ } else {
+ mark->fmark.fnum = buf->b_fnum;
+ }
+ }
+
+ return mark;
+}
+
+int mark_set_user(buf_T* buf, int name)
+{
+ const char* umf = (const char*) buf->b_p_umf;
+
+ if (!umf) {
+ return FAIL;
+ }
+
+ typval_T* out = xcalloc(sizeof(typval_T), 1);
+ call_umf(umf, name, out, "set");
+ tv_free(out);
+
+ return OK;
+}
+
/// Get marks that are actually motions but return them as marks
///
/// Gets the following motions as marks: '{', '}', '(', ')'
@@ -653,20 +797,16 @@ fmark_T *getnextmark(pos_T *startpos, int dir, int begin_line)
return result;
}
-/*
- * For an xtended filemark: set the fnum from the fname.
- * This is used for marks obtained from the .shada file. It's postponed
- * until the mark is used to avoid a long startup delay.
- */
+// For an xtended filemark: set the fnum from the fname.
+// This is used for marks obtained from the .shada file. It's postponed
+// until the mark is used to avoid a long startup delay.
static void fname2fnum(xfmark_T *fm)
{
char_u *p;
if (fm->fname != NULL) {
- /*
- * First expand "~/" in the file name to the home directory.
- * Don't expand the whole name, it may contain other '~' chars.
- */
+ // First expand "~/" in the file name to the home directory.
+ // Don't expand the whole name, it may contain other '~' chars.
if (fm->fname[0] == '~' && (fm->fname[1] == '/'
#ifdef BACKSLASH_IN_FILENAME
|| fm->fname[1] == '\\'
@@ -674,7 +814,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 {
@@ -682,19 +822,17 @@ static void fname2fnum(xfmark_T *fm)
}
// Try to shorten the file name.
- os_dirname(IObuff, IOSIZE);
- p = path_shorten_fname(NameBuff, IObuff);
+ os_dirname((char_u *)IObuff, IOSIZE);
+ p = (char_u *)path_shorten_fname(NameBuff, (char *)IObuff);
// buflist_new() will call fmarks_check_names()
(void)buflist_new((char *)NameBuff, (char *)p, (linenr_T)1, 0);
}
}
-/*
- * Check all file marks for a name that matches the file name in buf.
- * May replace the name with an fnum.
- * Used for marks that come from the .shada file.
- */
+// Check all file marks for a name that matches the file name in buf.
+// May replace the name with an fnum.
+// Used for marks that come from the .shada file.
void fmarks_check_names(buf_T *buf)
{
char_u *name = (char_u *)buf->b_ffname;
@@ -704,22 +842,22 @@ void fmarks_check_names(buf_T *buf)
return;
}
- for (i = 0; i < NGLOBALMARKS; ++i) {
- fmarks_check_one(&namedfm[i], name, buf);
+ for (i = 0; i < NGLOBALMARKS; i++) {
+ fmarks_check_one(&namedfm[i], (char *)name, buf);
}
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- for (i = 0; i < wp->w_jumplistlen; ++i) {
- fmarks_check_one(&wp->w_jumplist[i], name, buf);
+ for (i = 0; i < wp->w_jumplistlen; i++) {
+ fmarks_check_one(&wp->w_jumplist[i], (char *)name, buf);
}
}
}
-static void fmarks_check_one(xfmark_T *fm, char_u *name, buf_T *buf)
+static void fmarks_check_one(xfmark_T *fm, char *name, buf_T *buf)
{
if (fm->fmark.fnum == 0
&& fm->fname != NULL
- && FNAMECMP(name, fm->fname) == 0) {
+ && path_fnamecmp(name, fm->fname) == 0) {
fm->fmark.fnum = buf->b_fnum;
XFREE_CLEAR(fm->fname);
}
@@ -792,39 +930,35 @@ void clrallmarks(buf_T *const buf)
buf->b_changelistlen = 0;
}
-/*
- * Get name of file from a filemark.
- * When it's in the current buffer, return the text at the mark.
- * Returns an allocated string.
- */
+// Get name of file from a filemark.
+// When it's in the current buffer, return the text at the mark.
+// Returns an allocated string.
char_u *fm_getname(fmark_T *fmark, int lead_len)
{
if (fmark->fnum == curbuf->b_fnum) { // current buffer
- return mark_line(&(fmark->mark), lead_len);
+ return (char_u *)mark_line(&(fmark->mark), lead_len);
}
return (char_u *)buflist_nr2name(fmark->fnum, false, true);
}
-/*
- * Return the line at mark "mp". Truncate to fit in window.
- * The returned string has been allocated.
- */
-static char_u *mark_line(pos_T *mp, int lead_len)
+/// Return the line at mark "mp". Truncate to fit in window.
+/// The returned string has been allocated.
+static char *mark_line(pos_T *mp, int lead_len)
{
- char_u *s, *p;
+ char *s, *p;
int len;
if (mp->lnum == 0 || mp->lnum > curbuf->b_ml.ml_line_count) {
- return vim_strsave((char_u *)"-invalid-");
+ return xstrdup("-invalid-");
}
assert(Columns >= 0);
// Allow for up to 5 bytes per character.
- s = vim_strnsave((char_u *)skipwhite((char *)ml_get(mp->lnum)), (size_t)Columns * 5);
+ s = xstrnsave(skipwhite(ml_get(mp->lnum)), (size_t)Columns * 5);
// Truncate the line to fit it in the window
len = 0;
for (p = s; *p != NUL; MB_PTR_ADV(p)) {
- len += ptr2cells((char *)p);
+ len += ptr2cells(p);
if (len >= Columns - lead_len) {
break;
}
@@ -833,9 +967,7 @@ static char_u *mark_line(pos_T *mp, int lead_len)
return s;
}
-/*
- * print the marks
- */
+// print the marks
void ex_marks(exarg_T *eap)
{
char_u *arg = (char_u *)eap->arg;
@@ -848,10 +980,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 {
@@ -908,10 +1040,10 @@ static void show_one_mark(int c, char_u *arg, pos_T *p, char_u *name_arg, int cu
&& p->lnum != 0) {
// don't output anything if 'q' typed at --more-- prompt
if (name == NULL && current) {
- name = mark_line(p, 15);
+ name = (char_u *)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,10 +1054,9 @@ 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
}
if (mustfree) {
xfree(name);
@@ -933,9 +1064,7 @@ static void show_one_mark(int c, char_u *arg, pos_T *p, char_u *name_arg, int cu
}
}
-/*
- * ":delmarks[!] [marks]"
- */
+// ":delmarks[!] [marks]"
void ex_delmarks(exarg_T *eap)
{
char_u *p;
@@ -975,7 +1104,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 {
@@ -1016,25 +1145,23 @@ void ex_delmarks(exarg_T *eap)
}
}
-/*
- * print the jumplist
- */
+// print the jumplist
void ex_jumps(exarg_T *eap)
{
int i;
- char_u *name;
+ char *name;
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);
+ name = (char *)fm_getname(&curwin->w_jumplist[i].fmark, 16);
// Make sure to output the current indicator, even when on an wiped
// out buffer. ":filter" may still skip it.
if (name == NULL && i == curwin->w_jumplistidx) {
- name = vim_strsave((char_u *)"-invalid-");
+ name = xstrdup("-invalid-");
}
// apply :filter /pat/ or file name not available
if (name == NULL || message_filtered(name)) {
@@ -1058,7 +1185,6 @@ void ex_jumps(exarg_T *eap)
xfree(name);
os_breakcheck();
}
- ui_flush();
}
if (curwin->w_jumplistidx == curwin->w_jumplistlen) {
msg_puts("\n>");
@@ -1072,9 +1198,7 @@ void ex_clearjumps(exarg_T *eap)
curwin->w_jumplistidx = 0;
}
-/*
- * print the changelist
- */
+// print the changelist
void ex_changes(exarg_T *eap)
{
int i;
@@ -1083,7 +1207,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) {
@@ -1096,12 +1220,11 @@ void ex_changes(exarg_T *eap)
(long)curbuf->b_changelist[i].mark.lnum,
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));
+ name = (char_u *)mark_line(&curbuf->b_changelist[i].mark, 17);
+ msg_outtrans_attr((char *)name, HL_ATTR(HLF_D));
xfree(name);
os_breakcheck();
}
- ui_flush();
}
if (curwin->w_changelistidx == curbuf->b_changelistlen) {
msg_puts("\n>");
@@ -1137,17 +1260,15 @@ void ex_changes(exarg_T *eap)
*lp += amount_after; \
}
-/*
- * Adjust marks between line1 and line2 (inclusive) to move 'amount' lines.
- * Must be called before changed_*(), appended_lines() or deleted_lines().
- * May be called before or after changing the text.
- * When deleting lines line1 to line2, use an 'amount' of MAXLNUM: The marks
- * within this range are made invalid.
- * If 'amount_after' is non-zero adjust marks after line2.
- * Example: Delete lines 34 and 35: mark_adjust(34, 35, MAXLNUM, -2);
- * Example: Insert two lines below 55: mark_adjust(56, MAXLNUM, 2, 0);
- * or: mark_adjust(56, 55, MAXLNUM, 2);
- */
+// Adjust marks between line1 and line2 (inclusive) to move 'amount' lines.
+// Must be called before changed_*(), appended_lines() or deleted_lines().
+// May be called before or after changing the text.
+// When deleting lines line1 to line2, use an 'amount' of MAXLNUM: The marks
+// within this range are made invalid.
+// If 'amount_after' is non-zero adjust marks after line2.
+// Example: Delete lines 34 and 35: mark_adjust(34, 35, MAXLNUM, -2);
+// Example: Insert two lines below 55: mark_adjust(56, MAXLNUM, 2, 0);
+// or: mark_adjust(56, 55, MAXLNUM, 2);
void mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T amount_after,
ExtmarkOp op)
{
@@ -1242,9 +1363,7 @@ static void mark_adjust_internal(linenr_T line1, linenr_T line2, linenr_T amount
ONE_ADJUST_NODEL(&(saved_cursor.lnum));
}
- /*
- * Adjust items in all windows related to the current buffer.
- */
+ // Adjust items in all windows related to the current buffer.
FOR_ALL_TAB_WINDOWS(tab, win) {
if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
// Marks in the jumplist. When deleting lines, this may create
@@ -1386,12 +1505,10 @@ void mark_col_adjust(linenr_T lnum, colnr_T mincol, linenr_T lnum_amount, long c
// saved cursor for formatting
COL_ADJUST(&saved_cursor);
- /*
- * Adjust items in all windows related to the current buffer.
- */
+ // Adjust items in all windows related to the current buffer.
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));
}
@@ -1486,14 +1603,12 @@ void cleanup_jumplist(win_T *wp, bool checktail)
}
}
-/*
- * Copy the jumplist from window "from" to window "to".
- */
+// Copy the jumplist from window "from" to window "to".
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);
@@ -1710,14 +1825,12 @@ bool mark_set_local(const char name, buf_T *const buf, const fmark_T fm, const b
return true;
}
-/*
- * Free items in the jumplist of window "wp".
- */
+// Free items in the jumplist of window "wp".
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;
@@ -1754,11 +1867,11 @@ void mark_mb_adjustpos(buf_T *buf, pos_T *lp)
FUNC_ATTR_NONNULL_ALL
{
if (lp->col > 0 || lp->coladd > 1) {
- const char_u *const p = ml_get_buf(buf, lp->lnum, false);
+ const char_u *const p = (char_u *)ml_get_buf(buf, lp->lnum, false);
if (*p == NUL || (int)STRLEN(p) < lp->col) {
lp->col = 0;
} else {
- lp->col -= utf_head_off(p, p + lp->col);
+ lp->col -= utf_head_off((char *)p, (char *)p + lp->col);
}
// Reset "coladd" when the cursor would be on the right half of a
// double-wide character.
diff --git a/src/nvim/mark_defs.h b/src/nvim/mark_defs.h
index a78056c5f9..f9df0028db 100644
--- a/src/nvim/mark_defs.h
+++ b/src/nvim/mark_defs.h
@@ -5,10 +5,8 @@
#include "nvim/os/time.h"
#include "nvim/pos.h"
-/*
- * marks: positions in a file
- * (a normal mark is a lnum/col pair, the same as a file position)
- */
+// marks: positions in a file
+// (a normal mark is a lnum/col pair, the same as a file position)
/// Flags for outcomes when moving to a mark.
typedef enum {
@@ -88,4 +86,4 @@ typedef struct xfilemark {
#define INIT_XFMARK { INIT_FMARK, NULL }
-#endif // NVIM_MARK_DEFS_H
+#endif // NVIM_MARK_DEFS_H
diff --git a/src/nvim/match.c b/src/nvim/match.c
index 1c34c9f004..cd8c65cc02 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'.
@@ -446,7 +446,7 @@ static void next_search_hl(win_T *win, match_T *search_hl, match_T *shl, linenr_
char_u *ml;
matchcol = shl->rm.startpos[0].col;
- ml = ml_get_buf(shl->buf, lnum, false) + matchcol;
+ ml = (char_u *)ml_get_buf(shl->buf, lnum, false) + matchcol;
if (*ml == NUL) {
matchcol++;
shl->lnum = 0;
@@ -613,7 +613,7 @@ bool prepare_search_hl_line(win_T *wp, linenr_T lnum, colnr_T mincol, char_u **l
// Need to get the line again, a multi-line regexp may have made it
// invalid.
- *line = ml_get_buf(wp->w_buffer, lnum, false);
+ *line = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
if (shl->lnum != 0 && shl->lnum <= lnum) {
if (shl->lnum == lnum) {
@@ -721,7 +721,7 @@ int update_search_hl(win_T *wp, linenr_T lnum, colnr_T col, char_u **line, match
// Need to get the line again, a multi-line regexp
// may have made it invalid.
- *line = ml_get_buf(wp->w_buffer, lnum, false);
+ *line = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
if (shl->lnum == lnum) {
shl->startcol = shl->rm.startpos[0].col;
@@ -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) {
@@ -1159,9 +1159,9 @@ void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// skipping commands to find the next command.
void ex_match(exarg_T *eap)
{
- char_u *p;
- char_u *g = NULL;
- char_u *end;
+ char *p;
+ char *g = NULL;
+ char *end;
int c;
int id;
@@ -1178,16 +1178,16 @@ void ex_match(exarg_T *eap)
}
if (ends_excmd(*eap->arg)) {
- end = (char_u *)eap->arg;
+ end = eap->arg;
} else if ((STRNICMP(eap->arg, "none", 4) == 0
&& (ascii_iswhite(eap->arg[4]) || ends_excmd(eap->arg[4])))) {
- end = (char_u *)eap->arg + 4;
+ end = eap->arg + 4;
} else {
- p = skiptowhite((char_u *)eap->arg);
+ p = skiptowhite(eap->arg);
if (!eap->skip) {
- g = vim_strnsave((char_u *)eap->arg, (size_t)(p - (char_u *)eap->arg));
+ g = xstrnsave(eap->arg, (size_t)(p - eap->arg));
}
- p = (char_u *)skipwhite((char *)p);
+ p = skipwhite(p);
if (*p == NUL) {
// There must be two arguments.
xfree(g);
@@ -1196,7 +1196,7 @@ void ex_match(exarg_T *eap)
}
end = skip_regexp(p + 1, *p, true, NULL);
if (!eap->skip) {
- if (*end != NUL && !ends_excmd(*skipwhite((char *)end + 1))) {
+ if (*end != NUL && !ends_excmd(*skipwhite(end + 1))) {
xfree(g);
eap->errmsg = ex_errmsg(e_trailing_arg, (const char *)end);
return;
@@ -1207,13 +1207,13 @@ void ex_match(exarg_T *eap)
return;
}
- c = *end;
+ c = (uint8_t)(*end);
*end = NUL;
match_add(curwin, (const char *)g, (const char *)p + 1, 10, id,
NULL, NULL);
xfree(g);
- *end = (char_u)c;
+ *end = (char)c;
}
}
- eap->nextcmd = (char *)find_nextcmd(end);
+ eap->nextcmd = find_nextcmd(end);
}
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index af9e214d92..310ad05196 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -132,10 +132,8 @@ const uint8_t utf8len_tab_zero[] = {
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0, // F?
};
-/*
- * Canonical encoding names and their properties.
- * "iso-8859-n" is handled by enc_canonize() directly.
- */
+// Canonical encoding names and their properties.
+// "iso-8859-n" is handled by enc_canonize() directly.
static struct
{ const char *name; int prop; int codepage; }
enc_canon_table[] =
@@ -269,9 +267,7 @@ enc_canon_table[] =
#define IDX_COUNT 59
};
-/*
- * Aliases for encoding names.
- */
+// Aliases for encoding names.
static struct
{ const char *name; int canon; }
enc_alias_table[] =
@@ -342,29 +338,25 @@ enc_alias_table[] =
{ NULL, 0 }
};
-/*
- * Find encoding "name" in the list of canonical encoding names.
- * Returns -1 if not found.
- */
-static int enc_canon_search(const char_u *name)
+/// Find encoding "name" in the list of canonical encoding names.
+/// Returns -1 if not found.
+static int enc_canon_search(const char *name)
FUNC_ATTR_PURE
{
for (int i = 0; i < IDX_COUNT; i++) {
- if (STRCMP(name, enc_canon_table[i].name) == 0) {
+ if (strcmp(name, enc_canon_table[i].name) == 0) {
return i;
}
}
return -1;
}
-/*
- * Find canonical encoding "name" in the list and return its properties.
- * Returns 0 if not found.
- */
+// Find canonical encoding "name" in the list and return its properties.
+// Returns 0 if not found.
int enc_canon_props(const char_u *name)
FUNC_ATTR_PURE
{
- int i = enc_canon_search(name);
+ int i = enc_canon_search((char *)name);
if (i >= 0) {
return enc_canon_table[i].prop;
} else if (STRNCMP(name, "2byte-", 6) == 0) {
@@ -375,13 +367,11 @@ int enc_canon_props(const char_u *name)
return 0;
}
-/*
- * Return the size of the BOM for the current buffer:
- * 0 - no BOM
- * 2 - UCS-2 or UTF-16 BOM
- * 4 - UCS-4 BOM
- * 3 - UTF-8 BOM
- */
+// Return the size of the BOM for the current buffer:
+// 0 - no BOM
+// 2 - UCS-2 or UTF-16 BOM
+// 4 - UCS-4 BOM
+// 3 - UTF-8 BOM
int bomb_size(void)
FUNC_ATTR_PURE
{
@@ -389,7 +379,7 @@ int bomb_size(void)
if (curbuf->b_p_bomb && !curbuf->b_p_bin) {
if (*curbuf->b_p_fenc == NUL
- || STRCMP(curbuf->b_p_fenc, "utf-8") == 0) {
+ || strcmp(curbuf->b_p_fenc, "utf-8") == 0) {
n = 3;
} else if (STRNCMP(curbuf->b_p_fenc, "ucs-2", 5) == 0
|| STRNCMP(curbuf->b_p_fenc, "utf-16", 6) == 0) {
@@ -401,9 +391,7 @@ int bomb_size(void)
return n;
}
-/*
- * Remove all BOM from "s" by moving remaining text.
- */
+// Remove all BOM from "s" by moving remaining text.
void remove_bom(char_u *s)
{
char *p = (char *)s;
@@ -417,13 +405,11 @@ void remove_bom(char_u *s)
}
}
-/*
- * Get class of pointer:
- * 0 for blank or NUL
- * 1 for punctuation
- * 2 for an (ASCII) word character
- * >2 for other word characters
- */
+// Get class of pointer:
+// 0 for blank or NUL
+// 1 for punctuation
+// 2 for an (ASCII) word character
+// >2 for other word characters
int mb_get_class(const char_u *p)
FUNC_ATTR_PURE
{
@@ -445,9 +431,7 @@ int mb_get_class_tab(const char_u *p, const uint64_t *const chartab)
return utf_class_tab(utf_ptr2char((char *)p), chartab);
}
-/*
- * Return true if "c" is in "table".
- */
+// Return true if "c" is in "table".
static bool intable(const struct interval *table, size_t n_items, int c)
FUNC_ATTR_PURE
{
@@ -587,7 +571,7 @@ size_t mb_string2cells_len(const char *str, size_t size)
size_t clen = 0;
for (const char_u *p = (char_u *)str; *p != NUL && p < (char_u *)str + size;
- p += utfc_ptr2len_len(p, (int)size + (int)(p - (char_u *)str))) {
+ p += utfc_ptr2len_len((char *)p, (int)size + (int)(p - (char_u *)str))) {
clen += (size_t)utf_ptr2cells((char *)p);
}
@@ -646,22 +630,20 @@ int utf_ptr2char(const char *const p_in)
return p[0];
}
-/*
- * Convert a UTF-8 byte sequence to a wide character.
- * String is assumed to be terminated by NUL or after "n" bytes, whichever
- * comes first.
- * The function is safe in the sense that it never accesses memory beyond the
- * first "n" bytes of "s".
- *
- * On success, returns decoded codepoint, advances "s" to the beginning of
- * next character and decreases "n" accordingly.
- *
- * If end of string was reached, returns 0 and, if "n" > 0, advances "s" past
- * NUL byte.
- *
- * If byte sequence is illegal or incomplete, returns -1 and does not advance
- * "s".
- */
+// Convert a UTF-8 byte sequence to a wide character.
+// String is assumed to be terminated by NUL or after "n" bytes, whichever
+// comes first.
+// The function is safe in the sense that it never accesses memory beyond the
+// first "n" bytes of "s".
+//
+// On success, returns decoded codepoint, advances "s" to the beginning of
+// next character and decreases "n" accordingly.
+//
+// If end of string was reached, returns 0 and, if "n" > 0, advances "s" past
+// NUL byte.
+//
+// If byte sequence is illegal or incomplete, returns -1 and does not advance
+// "s".
static int utf_safe_read_char_adv(const char_u **s, size_t *n)
{
int c;
@@ -701,10 +683,8 @@ static int utf_safe_read_char_adv(const char_u **s, size_t *n)
return -1;
}
-/*
- * Get character at **pp and advance *pp to the next character.
- * Note: composing characters are skipped!
- */
+// Get character at **pp and advance *pp to the next character.
+// Note: composing characters are skipped!
int mb_ptr2char_adv(const char_u **const pp)
{
int c;
@@ -714,10 +694,8 @@ int mb_ptr2char_adv(const char_u **const pp)
return c;
}
-/*
- * Get character at **pp and advance *pp to the next character.
- * Note: composing characters are returned as separate characters.
- */
+// Get character at **pp and advance *pp to the next character.
+// Note: composing characters are returned as separate characters.
int mb_cptr2char_adv(const char_u **pp)
{
int c;
@@ -727,12 +705,10 @@ int mb_cptr2char_adv(const char_u **pp)
return c;
}
-/*
- * Check if the character pointed to by "p2" is a composing character when it
- * comes after "p1". For Arabic sometimes "ab" is replaced with "c", which
- * behaves like a composing character.
- */
-bool utf_composinglike(const char_u *p1, const char_u *p2)
+/// Check if the character pointed to by "p2" is a composing character when it
+/// comes after "p1". For Arabic sometimes "ab" is replaced with "c", which
+/// behaves like a composing character.
+bool utf_composinglike(const char *p1, const char *p2)
{
int c2;
@@ -754,21 +730,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);
+ && utf_composinglike((char *)p, (char *)p + len)) {
+ int cc = utf_ptr2char((char *)p + len);
for (;;) {
pcc[i++] = cc;
if (i == MAX_MCO) {
@@ -788,12 +762,10 @@ int utfc_ptr2char(const char_u *p, int *pcc)
return c;
}
-/*
- * Convert a UTF-8 byte string to a wide character. Also get up to MAX_MCO
- * composing characters. Use no more than p[maxlen].
- *
- * @param [out] pcc: composing chars, last one is 0
- */
+// Convert a UTF-8 byte string to a wide character. Also get up to MAX_MCO
+// composing characters. Use no more than p[maxlen].
+//
+// @param [out] pcc: composing chars, last one is 0
int utfc_ptr2char_len(const char_u *p, int *pcc, int maxlen)
{
assert(maxlen > 0);
@@ -811,7 +783,7 @@ int utfc_ptr2char_len(const char_u *p, int *pcc, int maxlen)
int len_cc = utf_ptr2len_len(p + len, maxlen - len);
safe = len_cc > 1 && len_cc <= maxlen - len;
if (!safe || (pcc[i] = utf_ptr2char((char *)p + len)) < 0x80
- || !(i == 0 ? utf_composinglike(p, p + len) : utf_iscomposing(pcc[i]))) {
+ || !(i == 0 ? utf_composinglike((char *)p, (char *)p + len) : utf_iscomposing(pcc[i]))) {
break;
}
len += len_cc;
@@ -849,24 +821,20 @@ int utf_ptr2len(const char *const p_in)
return len;
}
-/*
- * Return length of UTF-8 character, obtained from the first byte.
- * "b" must be between 0 and 255!
- * Returns 1 for an invalid first byte value.
- */
+// Return length of UTF-8 character, obtained from the first byte.
+// "b" must be between 0 and 255!
+// Returns 1 for an invalid first byte value.
int utf_byte2len(int b)
{
return utf8len_tab[b];
}
-/*
- * Get the length of UTF-8 byte sequence "p[size]". Does not include any
- * following composing characters.
- * Returns 1 for "".
- * Returns 1 for an illegal byte sequence (also in incomplete byte seq.).
- * Returns number > "size" for an incomplete byte sequence.
- * Never returns zero.
- */
+// Get the length of UTF-8 byte sequence "p[size]". Does not include any
+// following composing characters.
+// Returns 1 for "".
+// Returns 1 for an illegal byte sequence (also in incomplete byte seq.).
+// Returns number > "size" for an incomplete byte sequence.
+// Never returns zero.
int utf_ptr2len_len(const char_u *p, int size)
{
int len;
@@ -882,7 +850,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;
}
@@ -918,7 +886,7 @@ int utfc_ptr2len(const char *const p_in)
// skip all of them (otherwise the cursor would get stuck).
int prevlen = 0;
for (;;) {
- if (p[len] < 0x80 || !utf_composinglike(p + prevlen, p + len)) {
+ if (p[len] < 0x80 || !utf_composinglike((char *)p + prevlen, (char *)p + len)) {
return len;
}
@@ -928,13 +896,11 @@ int utfc_ptr2len(const char *const p_in)
}
}
-/*
- * Return the number of bytes the UTF-8 encoding of the character at "p[size]"
- * takes. This includes following composing characters.
- * Returns 0 for an empty string.
- * Returns 1 for an illegal char or an incomplete byte sequence.
- */
-int utfc_ptr2len_len(const char_u *p, int size)
+/// Return the number of bytes the UTF-8 encoding of the character at "p[size]"
+/// takes. This includes following composing characters.
+/// Returns 0 for an empty string.
+/// Returns 1 for an illegal char or an incomplete byte sequence.
+int utfc_ptr2len_len(const char *p, int size)
{
int len;
int prevlen;
@@ -942,35 +908,31 @@ int utfc_ptr2len_len(const char_u *p, int size)
if (size < 1 || *p == NUL) {
return 0;
}
- if (p[0] < 0x80 && (size == 1 || p[1] < 0x80)) { // be quick for ASCII
+ if ((uint8_t)p[0] < 0x80 && (size == 1 || (uint8_t)p[1] < 0x80)) { // be quick for ASCII
return 1;
}
// Skip over first UTF-8 char, stopping at a NUL byte.
- len = utf_ptr2len_len(p, size);
+ len = utf_ptr2len_len((char_u *)p, size);
// Check for illegal byte and incomplete byte sequence.
- if ((len == 1 && p[0] >= 0x80) || len > size) {
+ if ((len == 1 && (uint8_t)p[0] >= 0x80) || len > size) {
return 1;
}
- /*
- * Check for composing characters. We can handle only the first six, but
- * skip all of them (otherwise the cursor would get stuck).
- */
+ // Check for composing characters. We can handle only the first six, but
+ // skip all of them (otherwise the cursor would get stuck).
prevlen = 0;
while (len < size) {
int len_next_char;
- if (p[len] < 0x80) {
+ if ((uint8_t)p[len] < 0x80) {
break;
}
- /*
- * Next character length should not go beyond size to ensure that
- * utf_composinglike(...) does not read beyond size.
- */
- len_next_char = utf_ptr2len_len(p + len, size - len);
+ // Next character length should not go beyond size to ensure that
+ // utf_composinglike(...) does not read beyond size.
+ len_next_char = utf_ptr2len_len((char_u *)p + len, size - len);
if (len_next_char > size - len) {
break;
}
@@ -1048,20 +1010,16 @@ int utf_char2bytes(const int c, char *const buf)
}
}
-/*
- * Return true if "c" is a composing UTF-8 character. This means it will be
- * drawn on top of the preceding character.
- * Based on code from Markus Kuhn.
- */
+// Return true if "c" is a composing UTF-8 character. This means it will be
+// drawn on top of the preceding character.
+// Based on code from Markus Kuhn.
bool utf_iscomposing(int c)
{
return intable(combining, ARRAY_SIZE(combining), c);
}
-/*
- * Return true for characters that can be displayed in a normal way.
- * Only for characters of 0x100 and above!
- */
+// Return true for characters that can be displayed in a normal way.
+// Only for characters of 0x100 and above!
bool utf_printable(int c)
{
// Sorted list of non-overlapping intervals.
@@ -1076,12 +1034,10 @@ bool utf_printable(int c)
return !intable(nonprint, ARRAY_SIZE(nonprint), c);
}
-/*
- * Get class of a Unicode character.
- * 0: white space
- * 1: punctuation
- * 2 or bigger: some class of word character.
- */
+// Get class of a Unicode character.
+// 0: white space
+// 1: punctuation
+// 2 or bigger: some class of word character.
int utf_class(const int c)
{
return utf_class_tab(c, curbuf->b_chartab);
@@ -1210,11 +1166,9 @@ bool utf_ambiguous_width(int c)
|| intable(emoji_all, ARRAY_SIZE(emoji_all), c));
}
-/*
- * Generic conversion function for case operations.
- * Return the converted equivalent of "a", which is a UCS-4 character. Use
- * the given conversion "table". Uses binary search on "table".
- */
+// Generic conversion function for case operations.
+// Return the converted equivalent of "a", which is a UCS-4 character. Use
+// the given conversion "table". Uses binary search on "table".
static int utf_convert(int a, const convertStruct *const table, size_t n_items)
{
size_t start, mid, end; // indices into table
@@ -1240,10 +1194,8 @@ static int utf_convert(int a, const convertStruct *const table, size_t n_items)
}
}
-/*
- * Return the folded-case equivalent of "a", which is a UCS-4 character. Uses
- * simple case folding.
- */
+// Return the folded-case equivalent of "a", which is a UCS-4 character. Uses
+// simple case folding.
int utf_fold(int a)
{
if (a < 0x80) {
@@ -1543,17 +1495,16 @@ ssize_t mb_utf_index_to_bytes(const char_u *s, size_t len, size_t index, bool us
return -1;
}
-/*
- * Version of strnicmp() that handles multi-byte characters.
- * Needed for Big5, Shift-JIS and UTF-8 encoding. Other DBCS encodings can
- * probably use strnicmp(), because there are no ASCII characters in the
- * second byte.
- * Returns zero if s1 and s2 are equal (ignoring case), the difference between
- * two characters otherwise.
- */
-int mb_strnicmp(const char_u *s1, const char_u *s2, const size_t nn)
+/// Version of strnicmp() that handles multi-byte characters.
+/// Needed for Big5, Shift-JIS and UTF-8 encoding. Other DBCS encodings can
+/// probably use strnicmp(), because there are no ASCII characters in the
+/// second byte.
+///
+/// @return zero if s1 and s2 are equal (ignoring case), the difference between
+/// two characters otherwise.
+int mb_strnicmp(const char *s1, const char *s2, const size_t nn)
{
- return utf_strnicmp(s1, s2, nn, nn);
+ return utf_strnicmp((char_u *)s1, (char_u *)s2, nn, nn);
}
/// Compare strings case-insensitively
@@ -1570,13 +1521,11 @@ int mb_strnicmp(const char_u *s1, const char_u *s2, const size_t nn)
/// @return 0 if strings are equal, <0 if s1 < s2, >0 if s1 > s2.
int mb_stricmp(const char *s1, const char *s2)
{
- return mb_strnicmp((const char_u *)s1, (const char_u *)s2, MAXCOL);
+ return mb_strnicmp(s1, s2, MAXCOL);
}
-/*
- * "g8": show bytes of the UTF-8 char under the cursor. Doesn't matter what
- * 'encoding' has been set to.
- */
+// "g8": show bytes of the UTF-8 char under the cursor. Doesn't matter what
+// 'encoding' has been set to.
void show_utf8(void)
{
int len;
@@ -1587,7 +1536,7 @@ void show_utf8(void)
// Get the byte length of the char under the cursor, including composing
// characters.
- line = get_cursor_pos_ptr();
+ line = (char_u *)get_cursor_pos_ptr();
len = utfc_ptr2len((char *)line);
if (len == 0) {
msg("NUL");
@@ -1595,7 +1544,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) {
@@ -1620,22 +1569,25 @@ void show_utf8(void)
/// "base" must be the start of the string, which must be NUL terminated.
/// If "p" points to the NUL at the end of the string return 0.
/// Returns 0 when already at the first byte of a character.
-int utf_head_off(const char_u *base, const char_u *p)
+int utf_head_off(const char *base_in, const char *p_in)
{
int c;
int len;
- if (*p < 0x80) { // be quick for ASCII
+ if ((uint8_t)(*p_in) < 0x80) { // be quick for ASCII
return 0;
}
+ const uint8_t *base = (uint8_t *)base_in;
+ const uint8_t *p = (uint8_t *)p_in;
+
// Skip backwards over trailing bytes: 10xx.xxxx
// Skip backwards again if on a composing char.
- const char_u *q;
- for (q = p;; --q) {
+ const uint8_t *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) {}
+ const uint8_t *s;
+ for (s = q; (s[1] & 0xc0) == 0x80; s++) {}
// Move q to the first byte of this char.
while (q > base && (*q & 0xc0) == 0x80) {
@@ -1659,7 +1611,7 @@ int utf_head_off(const char_u *base, const char_u *p)
if (arabic_maycombine(c)) {
// Advance to get a sneak-peak at the next char
- const char_u *j = q;
+ const uint8_t *j = q;
j--;
// Move j to the first byte of this char.
while (j > base && (*j & 0xc0) == 0x80) {
@@ -1920,9 +1872,7 @@ int utf_cp_head_off(const char_u *base, const char_u *p)
return i;
}
-/*
- * Find the next illegal byte sequence.
- */
+// Find the next illegal byte sequence.
void utf_find_illegal(void)
{
pos_T pos = curwin->w_cursor;
@@ -1932,7 +1882,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'.
@@ -1941,10 +1891,10 @@ void utf_find_illegal(void)
curwin->w_cursor.coladd = 0;
for (;;) {
- p = get_cursor_pos_ptr();
+ p = (char_u *)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;
}
@@ -1958,12 +1908,12 @@ void utf_find_illegal(void)
if (*p >= 0x80 && (len == 1
|| utf_char2len(utf_ptr2char((char *)p)) != len)) {
if (vimconv.vc_type == CONV_NONE) {
- curwin->w_cursor.col += (colnr_T)(p - get_cursor_pos_ptr());
+ curwin->w_cursor.col += (colnr_T)(p - (char_u *)get_cursor_pos_ptr());
} else {
int l;
len = (int)(p - tofree);
- for (p = get_cursor_pos_ptr(); *p != NUL && len-- > 0; p += l) {
+ for (p = (char_u *)get_cursor_pos_ptr(); *p != NUL && len-- > 0; p += l) {
l = utf_ptr2len((char *)p);
curwin->w_cursor.col += l;
}
@@ -1975,7 +1925,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 +1939,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;
@@ -2013,10 +1962,8 @@ bool utf_valid_string(const char_u *s, const char_u *end)
return true;
}
-/*
- * If the cursor moves on an trail byte, set the cursor on the lead byte.
- * Thus it moves left if necessary.
- */
+// If the cursor moves on an trail byte, set the cursor on the lead byte.
+// Thus it moves left if necessary.
void mb_adjust_cursor(void)
{
mark_mb_adjustpos(curbuf, &curwin->w_cursor);
@@ -2033,7 +1980,7 @@ void mb_check_adjust_col(void *win_)
// Column 0 is always valid.
if (oldcol != 0) {
- char *p = (char *)ml_get_buf(win->w_buffer, win->w_cursor.lnum, false);
+ char *p = ml_get_buf(win->w_buffer, win->w_cursor.lnum, false);
colnr_T len = (colnr_T)STRLEN(p);
// Empty line or invalid column?
@@ -2045,7 +1992,7 @@ void mb_check_adjust_col(void *win_)
win->w_cursor.col = len - 1;
}
// Move the cursor to the head byte.
- win->w_cursor.col -= utf_head_off((char_u *)p, (char_u *)p + win->w_cursor.col);
+ win->w_cursor.col -= utf_head_off(p, p + win->w_cursor.col);
}
// Reset `coladd` when the cursor would be on the right half of a
@@ -2147,10 +2094,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,31 +2106,29 @@ 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) {
+ char *p, *s;
+ if (strcmp(enc, "default") == 0) {
// Use the default encoding as found by set_init_1().
- return vim_strsave(fenc_default);
+ return xstrdup(fenc_default);
}
// copy "enc" to allocated memory, with room for two '-'
- char_u *r = xmalloc(STRLEN(enc) + 3);
+ char *r = xmalloc(STRLEN(enc) + 3);
// Make it all lower case and replace '_' with '-'.
p = r;
- for (s = enc; *s != NUL; ++s) {
+ for (s = enc; *s != NUL; s++) {
if (*s == '_') {
*p++ = '-';
} else {
- *p++ = (char_u)TOLOWER_ASC(*s);
+ *p++ = (char)TOLOWER_ASC(*s);
}
}
*p = NUL;
@@ -2215,6 +2158,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) {
@@ -2223,19 +2167,19 @@ char_u *enc_canonize(char_u *enc) FUNC_ATTR_NONNULL_RET
} else if ((i = enc_alias_search(p)) >= 0) {
// alias recognized, get canonical name
xfree(r);
- r = vim_strsave((char_u *)enc_canon_table[i].name);
+ r = xstrdup(enc_canon_table[i].name);
}
return r;
}
/// Search for an encoding alias of "name".
/// Returns -1 when not found.
-static int enc_alias_search(const char_u *name)
+static int enc_alias_search(const char *name)
{
int i;
- for (i = 0; enc_alias_table[i].name != NULL; ++i) {
- if (STRCMP(name, enc_alias_table[i].name) == 0) {
+ 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;
}
}
@@ -2246,10 +2190,8 @@ static int enc_alias_search(const char_u *name)
# include <langinfo.h>
#endif
-/*
- * Get the canonicalized encoding of the current locale.
- * Returns an allocated string when successful, NULL when not.
- */
+// Get the canonicalized encoding of the current locale.
+// Returns an allocated string when successful, NULL when not.
char_u *enc_locale(void)
{
int i;
@@ -2310,17 +2252,15 @@ enc_locale_copy_enc:
buf[i] = NUL;
}
- return enc_canonize((char_u *)buf);
+ return (char_u *)enc_canonize(buf);
}
#if defined(HAVE_ICONV)
-/*
- * Call iconv_open() with a check if iconv() works properly (there are broken
- * versions).
- * Returns (void *)-1 if failed.
- * (should return iconv_t, but that causes problems with prototypes).
- */
+// Call iconv_open() with a check if iconv() works properly (there are broken
+// versions).
+// Returns (void *)-1 if failed.
+// (should return iconv_t, but that causes problems with prototypes).
void *my_iconv_open(char_u *to, char_u *from)
{
iconv_t fd;
@@ -2333,16 +2273,14 @@ 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) {
- /*
- * Do a dummy iconv() call to check if it actually works. There is a
- * version of iconv() on Linux that is broken. We can't ignore it,
- * because it's wide-spread. The symptoms are that after outputting
- * the initial shift state the "to" pointer is NULL and conversion
- * stops for no apparent reason after about 8160 characters.
- */
+ // Do a dummy iconv() call to check if it actually works. There is a
+ // version of iconv() on Linux that is broken. We can't ignore it,
+ // because it's wide-spread. The symptoms are that after outputting
+ // the initial shift state the "to" pointer is NULL and conversion
+ // stops for no apparent reason after about 8160 characters.
p = (char *)tobuf;
tolen = ICONV_TESTLEN;
(void)iconv(fd, NULL, NULL, &p, &tolen);
@@ -2358,13 +2296,11 @@ void *my_iconv_open(char_u *to, char_u *from)
return (void *)fd;
}
-/*
- * Convert the string "str[slen]" with iconv().
- * If "unconvlenp" is not NULL handle the string ending in an incomplete
- * sequence and set "*unconvlenp" to the length of it.
- * Returns the converted string in allocated memory. NULL for an error.
- * If resultlenp is not NULL, sets it to the result length in bytes.
- */
+// Convert the string "str[slen]" with iconv().
+// If "unconvlenp" is not NULL handle the string ending in an incomplete
+// sequence and set "*unconvlenp" to the length of it.
+// Returns the converted string in allocated memory. NULL for an error.
+// If resultlenp is not NULL, sets it to the result length in bytes.
static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, size_t slen,
size_t *unconvlenp, size_t *resultlenp)
{
@@ -2424,7 +2360,7 @@ static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, size_t slen
if (utf_ptr2cells(from) > 1) {
*to++ = '?';
}
- l = utfc_ptr2len_len((const char_u *)from, (int)fromlen);
+ l = utfc_ptr2len_len(from, (int)fromlen);
from += l;
fromlen -= (size_t)l;
} else if (ICONV_ERRNO != ICONV_E2BIG) {
@@ -2444,23 +2380,22 @@ 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);
}
/// As convert_setup(), but only when from_unicode_is_utf8 is true will all
/// "from" unicode charsets be considered utf-8. Same for "to".
-int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, char_u *to,
+int convert_setup_ext(vimconv_T *vcp, char *from, bool from_unicode_is_utf8, char *to,
bool to_unicode_is_utf8)
{
int from_prop;
@@ -2478,12 +2413,12 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, c
// No conversion when one of the names is empty or they are equal.
if (from == NULL || *from == NUL || to == NULL || *to == NUL
- || STRCMP(from, to) == 0) {
+ || strcmp(from, to) == 0) {
return OK;
}
- from_prop = enc_canon_props(from);
- to_prop = enc_canon_props(to);
+ from_prop = enc_canon_props((char_u *)from);
+ to_prop = enc_canon_props((char_u *)to);
if (from_unicode_is_utf8) {
from_is_utf8 = from_prop & ENC_UNICODE;
} else {
@@ -2513,8 +2448,8 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8, c
#ifdef HAVE_ICONV
else { // NOLINT(readability/braces)
// Use iconv() for conversion.
- vcp->vc_fd = (iconv_t)my_iconv_open(to_is_utf8 ? (char_u *)"utf-8" : to,
- from_is_utf8 ? (char_u *)"utf-8" : from);
+ vcp->vc_fd = (iconv_t)my_iconv_open(to_is_utf8 ? (char_u *)"utf-8" : (char_u *)to,
+ from_is_utf8 ? (char_u *)"utf-8" : (char_u *)from);
if (vcp->vc_fd != (iconv_t)-1) {
vcp->vc_type = CONV_ICONV;
vcp->vc_factor = 4; // could be longer too...
@@ -2528,23 +2463,19 @@ 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);
}
-/*
- * Like string_convert(), but when "unconvlenp" is not NULL and there are is
- * an incomplete sequence at the end it is not converted and "*unconvlenp" is
- * set to the number of remaining bytes.
- */
+// Like string_convert(), but when "unconvlenp" is not NULL and there are is
+// an incomplete sequence at the end it is not converted and "*unconvlenp" is
+// set to the number of remaining bytes.
char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp,
size_t *unconvlenp)
{
@@ -2560,14 +2491,14 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
len = *lenp;
}
if (len == 0) {
- return vim_strsave((char_u *)"");
+ return (char_u *)xstrdup("");
}
switch (vcp->vc_type) {
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 +2516,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 +2679,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,12 +2788,12 @@ 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
+ if (tv_check_for_string_arg(argvars, 0) == FAIL
|| argvars[0].vval.v_string == NULL) {
return;
}
diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h
index 2a9afcbd03..b499f33cc6 100644
--- a/src/nvim/mbyte.h
+++ b/src/nvim/mbyte.h
@@ -11,12 +11,10 @@
#include "nvim/os/os_defs.h" // For indirect
#include "nvim/types.h" // for char_u
-/*
- * Return byte length of character that starts with byte "b".
- * Returns 1 for a single-byte character.
- * MB_BYTE2LEN_CHECK() can be used to count a special key as one byte.
- * Don't call MB_BYTE2LEN(b) with b < 0 or b > 255!
- */
+// Return byte length of character that starts with byte "b".
+// Returns 1 for a single-byte character.
+// MB_BYTE2LEN_CHECK() can be used to count a special key as one byte.
+// Don't call MB_BYTE2LEN(b) with b < 0 or b > 255!
#define MB_BYTE2LEN(b) utf8len_tab[b]
#define MB_BYTE2LEN_CHECK(b) (((b) < 0 || (b) > 255) ? 1 : utf8len_tab[b])
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 216ee26620..bb9be0766e 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;
@@ -170,7 +170,7 @@ void mf_close(memfile_T *mfp, bool del_file)
emsg(_(e_swapclose));
}
if (del_file && mfp->mf_fname != NULL) {
- os_remove((char *)mfp->mf_fname);
+ os_remove(mfp->mf_fname);
}
// free entries in used list
@@ -210,7 +210,7 @@ void mf_close_file(buf_T *buf, bool getlines)
mfp->mf_fd = -1;
if (mfp->mf_fname != NULL) {
- os_remove((char *)mfp->mf_fname); // delete the swap file
+ os_remove(mfp->mf_fname); // delete the swap file
mf_free_fnames(mfp);
}
}
@@ -749,10 +749,10 @@ 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_ffname = (char_u *)FullName_save((char *)mfp->mf_fname, false);
+ mfp->mf_ffname = (char_u *)FullName_save(mfp->mf_fname, false);
}
/// Make name of memfile's swapfile a full path.
@@ -762,7 +762,7 @@ void mf_fullname(memfile_T *mfp)
{
if (mfp != NULL && mfp->mf_fname != NULL && mfp->mf_ffname != NULL) {
xfree(mfp->mf_fname);
- mfp->mf_fname = mfp->mf_ffname;
+ mfp->mf_fname = (char *)mfp->mf_ffname;
mfp->mf_ffname = NULL;
}
}
@@ -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);
@@ -789,7 +789,7 @@ static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags)
/// exist yet. If there is a symbolic link, this is most likely an attack.
FileInfo file_info;
if ((flags & O_CREAT)
- && os_fileinfo_link((char *)mfp->mf_fname, &file_info)) {
+ && os_fileinfo_link(mfp->mf_fname, &file_info)) {
mfp->mf_fd = -1;
emsg(_("E300: Swap file already exists (symlink attack?)"));
} else {
diff --git a/src/nvim/memfile_defs.h b/src/nvim/memfile_defs.h
index 537d3e5f65..d1e8fd0fb4 100644
--- a/src/nvim/memfile_defs.h
+++ b/src/nvim/memfile_defs.h
@@ -88,7 +88,7 @@ typedef struct mf_blocknr_trans_item {
/// A memory file.
typedef struct memfile {
- char_u *mf_fname; /// name of the file
+ char *mf_fname; /// name of the file
char_u *mf_ffname; /// idem, full path
int mf_fd; /// file descriptor
bhdr_T *mf_free_first; /// first block header in free list
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 23bc5d59c8..9d1ad5903d 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -5,36 +5,34 @@
// #define CHECK(c, s) do { if (c) emsg(s); } while (0)
#define CHECK(c, s) do {} while (0)
-/*
- * memline.c: Contains the functions for appending, deleting and changing the
- * text lines. The memfile functions are used to store the information in
- * blocks of memory, backed up by a file. The structure of the information is
- * a tree. The root of the tree is a pointer block. The leaves of the tree
- * are data blocks. In between may be several layers of pointer blocks,
- * forming branches.
- *
- * Three types of blocks are used:
- * - Block nr 0 contains information for recovery
- * - Pointer blocks contain list of pointers to other blocks.
- * - Data blocks contain the actual text.
- *
- * Block nr 0 contains the block0 structure (see below).
- *
- * Block nr 1 is the first pointer block. It is the root of the tree.
- * Other pointer blocks are branches.
- *
- * If a line is too big to fit in a single page, the block containing that
- * line is made big enough to hold the line. It may span several pages.
- * Otherwise all blocks are one page.
- *
- * A data block that was filled when starting to edit a file and was not
- * changed since then, can have a negative block number. This means that it
- * has not yet been assigned a place in the file. When recovering, the lines
- * in this data block can be read from the original file. When the block is
- * changed (lines appended/deleted/changed) or when it is flushed it gets a
- * positive number. Use mf_trans_del() to get the new number, before calling
- * mf_get().
- */
+// memline.c: Contains the functions for appending, deleting and changing the
+// text lines. The memfile functions are used to store the information in
+// blocks of memory, backed up by a file. The structure of the information is
+// a tree. The root of the tree is a pointer block. The leaves of the tree
+// are data blocks. In between may be several layers of pointer blocks,
+// forming branches.
+//
+// Three types of blocks are used:
+// - Block nr 0 contains information for recovery
+// - Pointer blocks contain list of pointers to other blocks.
+// - Data blocks contain the actual text.
+//
+// Block nr 0 contains the block0 structure (see below).
+//
+// Block nr 1 is the first pointer block. It is the root of the tree.
+// Other pointer blocks are branches.
+//
+// If a line is too big to fit in a single page, the block containing that
+// line is made big enough to hold the line. It may span several pages.
+// Otherwise all blocks are one page.
+//
+// A data block that was filled when starting to edit a file and was not
+// changed since then, can have a negative block number. This means that it
+// has not yet been assigned a place in the file. When recovering, the lines
+// in this data block can be read from the original file. When the block is
+// changed (lines appended/deleted/changed) or when it is flushed it gets a
+// positive number. Use mf_trans_del() to get the new number, before calling
+// mf_get().
#include <assert.h>
#include <errno.h>
@@ -90,9 +88,7 @@ typedef struct pointer_entry PTR_EN; // block/line-count pair
#define BLOCK0_ID0 'b' // block 0 id 0
#define BLOCK0_ID1 '0' // block 0 id 1
-/*
- * pointer to a block, used in a pointer block
- */
+// pointer to a block, used in a pointer block
struct pointer_entry {
blocknr_T pe_bnum; // block number
linenr_T pe_line_count; // number of lines in this branch
@@ -100,9 +96,7 @@ struct pointer_entry {
int pe_page_count; // number of pages in block pe_bnum
};
-/*
- * A pointer block contains a list of branches in the tree.
- */
+// A pointer block contains a list of branches in the tree.
struct pointer_block {
uint16_t pb_id; // ID for pointer block: PTR_ID
uint16_t pb_count; // number of pointers in this block
@@ -111,13 +105,11 @@ struct pointer_block {
// followed by empty space until end of page
};
-/*
- * A data block is a leaf in the tree.
- *
- * The text of the lines is at the end of the block. The text of the first line
- * in the block is put at the end, the text of the second line in front of it,
- * etc. Thus the order of the lines is the opposite of the line number.
- */
+// A data block is a leaf in the tree.
+//
+// The text of the lines is at the end of the block. The text of the first line
+// in the block is put at the end, the text of the second line in front of it,
+// etc. Thus the order of the lines is the opposite of the line number.
struct data_block {
uint16_t db_id; // ID for data block: DATA_ID
unsigned db_free; // free space available
@@ -130,14 +122,12 @@ struct data_block {
// end of page
};
-/*
- * The low bits of db_index hold the actual index. The topmost bit is
- * used for the global command to be able to mark a line.
- * This method is not clean, but otherwise there would be at least one extra
- * byte used for each line.
- * The mark has to be in this place to keep it with the correct line when other
- * lines are inserted or deleted.
- */
+// The low bits of db_index hold the actual index. The topmost bit is
+// used for the global command to be able to mark a line.
+// This method is not clean, but otherwise there would be at least one extra
+// byte used for each line.
+// The mark has to be in this place to keep it with the correct line when other
+// lines are inserted or deleted.
#define DB_MARKED ((unsigned)1 << ((sizeof(unsigned) * 8) - 1))
#define DB_INDEX_MASK (~DB_MARKED)
@@ -149,28 +139,24 @@ struct data_block {
#define B0_FNAME_SIZE_CRYPT 890 // 10 bytes used for other things
#define B0_UNAME_SIZE 40
#define B0_HNAME_SIZE 40
-/*
- * Restrict the numbers to 32 bits, otherwise most compilers will complain.
- * This won't detect a 64 bit machine that only swaps a byte in the top 32
- * bits, but that is crazy anyway.
- */
+// Restrict the numbers to 32 bits, otherwise most compilers will complain.
+// This won't detect a 64 bit machine that only swaps a byte in the top 32
+// bits, but that is crazy anyway.
#define B0_MAGIC_LONG 0x30313233L
#define B0_MAGIC_INT 0x20212223L
#define B0_MAGIC_SHORT 0x10111213L
#define B0_MAGIC_CHAR 0x55
-/*
- * Block zero holds all info about the swap file.
- *
- * NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing
- * swap files unusable!
- *
- * If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in vim.h!!
- *
- * This block is built up of single bytes, to make it portable across
- * different machines. b0_magic_* is used to check the byte order and size of
- * variables, because the rest of the swap file is not portable.
- */
+// Block zero holds all info about the swap file.
+//
+// NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing
+// swap files unusable!
+//
+// If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in vim.h!!
+//
+// This block is built up of single bytes, to make it portable across
+// different machines. b0_magic_* is used to check the byte order and size of
+// variables, because the rest of the swap file is not portable.
struct block0 {
char_u b0_id[2]; ///< ID for block 0: BLOCK0_ID0 and BLOCK0_ID1.
char_u b0_version[10]; // Vim version string
@@ -187,18 +173,14 @@ struct block0 {
char_u b0_magic_char; // check for last char
};
-/*
- * Note: b0_dirty and b0_flags are put at the end of the file name. For very
- * long file names in older versions of Vim they are invalid.
- * The 'fileencoding' comes before b0_flags, with a NUL in front. But only
- * when there is room, for very long file names it's omitted.
- */
+// Note: b0_dirty and b0_flags are put at the end of the file name. For very
+// long file names in older versions of Vim they are invalid.
+// The 'fileencoding' comes before b0_flags, with a NUL in front. But only
+// when there is room, for very long file names it's omitted.
#define B0_DIRTY 0x55
#define b0_dirty b0_fname[B0_FNAME_SIZE_ORG - 1]
-/*
- * The b0_flags field is new in Vim 7.0.
- */
+// The b0_flags field is new in Vim 7.0.
#define b0_flags b0_fname[B0_FNAME_SIZE_ORG - 2]
// The lowest two bits contain the fileformat. Zero means it's not set
@@ -216,17 +198,13 @@ struct block0 {
#define STACK_INCR 5 // nr of entries added to ml_stack at a time
-/*
- * The line number where the first mark may be is remembered.
- * If it is 0 there are no marks at all.
- * (always used for the current buffer only, no buffer change possible while
- * executing a global command).
- */
+// The line number where the first mark may be is remembered.
+// If it is 0 there are no marks at all.
+// (always used for the current buffer only, no buffer change possible while
+// executing a global command).
static linenr_T lowest_marked = 0;
-/*
- * arguments for ml_find_line()
- */
+// arguments for ml_find_line()
#define ML_DELETE 0x11 // delete line
#define ML_INSERT 0x12 // insert line
#define ML_FIND 0x13 // just find the line
@@ -253,9 +231,7 @@ int ml_open(buf_T *buf)
PTR_BL *pp;
DATA_BL *dp;
- /*
- * init fields in memline struct
- */
+ // init fields in memline struct
buf->b_ml.ml_stack_size = 0; // no stack yet
buf->b_ml.ml_stack = NULL; // no stack yet
buf->b_ml.ml_stack_top = 0; // nothing in the stack
@@ -269,9 +245,7 @@ int ml_open(buf_T *buf)
buf->b_p_swf = false;
}
- /*
- * When 'updatecount' is non-zero swap file may be opened later.
- */
+ // When 'updatecount' is non-zero swap file may be opened later.
if (!buf->terminal && p_uc && buf->b_p_swf) {
buf->b_may_swap = true;
} else {
@@ -289,9 +263,7 @@ int ml_open(buf_T *buf)
buf->b_ml.ml_line_count = 1;
curwin->w_nrwidth_line_count = 0;
- /*
- * fill block0 struct and write page 0
- */
+ // fill block0 struct and write page 0
hp = mf_new(mfp, false, 1);
if (hp->bh_bnum != 0) {
iemsg(_("E298: Didn't get block nr 0?"));
@@ -319,21 +291,17 @@ int ml_open(buf_T *buf)
long_to_char(os_get_pid(), b0p->b0_pid);
}
- /*
- * Always sync block number 0 to disk, so we can check the file name in
- * the swap file in findswapname(). Don't do this for a help files or
- * a spell buffer though.
- * Only works when there's a swapfile, otherwise it's done when the file
- * is created.
- */
+ // Always sync block number 0 to disk, so we can check the file name in
+ // the swap file in findswapname(). Don't do this for a help files or
+ // a spell buffer though.
+ // Only works when there's a swapfile, otherwise it's done when the file
+ // is created.
mf_put(mfp, hp, true, false);
if (!buf->b_help && !B_SPELL(buf)) {
(void)mf_sync(mfp, 0);
}
- /*
- * Fill in root pointer block and write page 1.
- */
+ // Fill in root pointer block and write page 1.
if ((hp = ml_new_ptr(mfp)) == NULL) {
goto error;
}
@@ -349,9 +317,7 @@ int ml_open(buf_T *buf)
pp->pb_pointer[0].pe_line_count = 1; // line count after insertion
mf_put(mfp, hp, true, false);
- /*
- * Allocate first data block and create an empty line 1.
- */
+ // Allocate first data block and create an empty line 1.
hp = ml_new_data(mfp, false, 1);
if (hp->bh_bnum != 2) {
iemsg(_("E298: Didn't get block nr 2?"));
@@ -383,15 +349,13 @@ void ml_setname(buf_T *buf)
{
bool success = false;
memfile_T *mfp;
- char_u *fname;
+ char *fname;
char *dirp;
mfp = buf->b_ml.ml_mfp;
if (mfp->mf_fd < 0) { // there is no swap file yet
- /*
- * When 'updatecount' is 0 and 'noswapfile' there is no swap file.
- * For help files we will make a swap file now.
- */
+ // When 'updatecount' is 0 and 'noswapfile' there is no swap file.
+ // For help files we will make a swap file now.
if (p_uc != 0 && (cmdmod.cmod_flags & CMOD_NOSWAPFILE) == 0) {
ml_open_file(buf); // create a swap file
}
@@ -399,13 +363,13 @@ 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
break;
}
- fname = (char_u *)findswapname(buf, &dirp, (char *)mfp->mf_fname, &found_existing_dir);
+ fname = findswapname(buf, &dirp, mfp->mf_fname, &found_existing_dir);
// alloc's fname
if (dirp == NULL) { // out of memory
break;
@@ -415,7 +379,7 @@ void ml_setname(buf_T *buf)
}
// if the file name is the same we don't have to do anything
- if (FNAMECMP(fname, mfp->mf_fname) == 0) {
+ if (path_fnamecmp(fname, mfp->mf_fname) == 0) {
xfree(fname);
success = true;
break;
@@ -438,7 +402,7 @@ void ml_setname(buf_T *buf)
}
if (mfp->mf_fd == -1) { // need to (re)open the swap file
- mfp->mf_fd = os_open((char *)mfp->mf_fname, O_RDWR, 0);
+ mfp->mf_fd = os_open(mfp->mf_fname, O_RDWR, 0);
if (mfp->mf_fd < 0) {
// could not (re)open the swap file, what can we do????
emsg(_("E301: Oops, lost the swap file!!!"));
@@ -481,16 +445,16 @@ void ml_open_file(buf_T *buf)
// For a spell buffer use a temp file name.
if (buf->b_spell) {
- fname = vim_tempname();
+ fname = (char_u *)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 +470,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 +487,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 +516,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 +554,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
}
}
}
@@ -653,13 +617,11 @@ static void set_b0_fname(ZERO_BL *b0p, buf_T *buf)
} else {
char uname[B0_UNAME_SIZE];
- /*
- * For a file under the home directory of the current user, we try to
- * replace the home directory path with "~user". This helps when
- * editing the same file on different machines over a network.
- * First replace home dir path with "~/" with home_replace().
- * Then insert the user name to get "~user/".
- */
+ // For a file under the home directory of the current user, we try to
+ // replace the home directory path with "~user". This helps when
+ // editing the same file on different machines over a network.
+ // First replace home dir path with "~/" with home_replace().
+ // Then insert the user name to get "~user/".
home_replace(NULL, buf->b_ffname, (char *)b0p->b0_fname,
B0_FNAME_SIZE_CRYPT, true);
if (b0p->b0_fname[0] == '~') {
@@ -703,7 +665,7 @@ static void set_b0_fname(ZERO_BL *b0p, buf_T *buf)
/// not set.
static void set_b0_dir_flag(ZERO_BL *b0p, buf_T *buf)
{
- if (same_directory(buf->b_ml.ml_mfp->mf_fname, (char_u *)buf->b_ffname)) {
+ if (same_directory((char_u *)buf->b_ml.ml_mfp->mf_fname, (char_u *)buf->b_ffname)) {
b0p->b0_flags |= B0_SAME_DIR;
} else {
b0p->b0_flags &= (uint8_t) ~B0_SAME_DIR;
@@ -721,7 +683,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;
}
@@ -735,12 +697,12 @@ void ml_recover(bool checkext)
{
buf_T *buf = NULL;
memfile_T *mfp = NULL;
- char_u *fname;
- char_u *fname_used = NULL;
+ char *fname;
+ char *fname_used = NULL;
bhdr_T *hp = NULL;
ZERO_BL *b0p;
int b0_ff;
- char_u *b0_fenc = NULL;
+ char *b0_fenc = NULL;
PTR_BL *pp;
DATA_BL *dp;
infoptr_T *ip;
@@ -748,7 +710,7 @@ void ml_recover(bool checkext)
int len;
bool directly;
linenr_T lnum;
- char_u *p;
+ char *p;
int i;
long error;
bool cannot_open;
@@ -764,15 +726,15 @@ 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);
// If the file name ends in ".s[a-w][a-z]" we assume this is the swap file.
// Otherwise a search is done to find the swap file(s).
- fname = (char_u *)curbuf->b_fname;
+ fname = curbuf->b_fname;
if (fname == NULL) { // When there is no file name
- fname = (char_u *)"";
+ fname = "";
}
len = (int)STRLEN(fname);
if (checkext && len >= 4
@@ -780,12 +742,12 @@ void ml_recover(bool checkext)
&& vim_strchr("abcdefghijklmnopqrstuvw", TOLOWER_ASC(fname[len - 2])) != NULL
&& ASCII_ISALPHA(fname[len - 1])) {
directly = true;
- fname_used = vim_strsave(fname); // make a copy for mf_open()
+ fname_used = xstrdup(fname); // make a copy for mf_open()
} else {
directly = false;
// count the number of matching swap files
- len = recover_names(fname, FALSE, 0, NULL);
+ len = recover_names((char_u *)fname, false, 0, NULL);
if (len == 0) { // no swap files found
semsg(_("E305: No swap file found for %s"), fname);
goto theend;
@@ -794,16 +756,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((char_u *)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((char_u *)fname, false, i, &fname_used);
}
if (fname_used == NULL) {
goto theend; // user chose invalid number.
@@ -813,15 +775,11 @@ void ml_recover(bool checkext)
getout(1);
}
- /*
- * Allocate a buffer structure for the swap file that is used for recovery.
- * Only the memline in it is really used.
- */
+ // Allocate a buffer structure for the swap file that is used for recovery.
+ // Only the memline in it is really used.
buf = xmalloc(sizeof(buf_T));
- /*
- * init fields in memline struct
- */
+ // init fields in memline struct
buf->b_ml.ml_stack_size = 0; // no stack yet
buf->b_ml.ml_stack = NULL; // no stack yet
buf->b_ml.ml_stack_top = 0; // nothing in the stack
@@ -830,11 +788,9 @@ void ml_recover(bool checkext)
buf->b_ml.ml_locked = NULL; // no locked block
buf->b_ml.ml_flags = 0;
- /*
- * open the memfile from the old swap file
- */
- p = vim_strsave(fname_used); // save "fname_used" for the message:
- // mf_open() will consume "fname_used"!
+ // open the memfile from the old swap file
+ p = xstrdup(fname_used); // save "fname_used" for the message:
+ // mf_open() will consume "fname_used"!
mfp = mf_open(fname_used, O_RDONLY);
fname_used = p;
if (mfp == NULL || mfp->mf_fd < 0) {
@@ -843,17 +799,13 @@ void ml_recover(bool checkext)
}
buf->b_ml.ml_mfp = mfp;
- /*
- * The page size set in mf_open() might be different from the page size
- * used in the swap file, we must get it from block 0. But to read block
- * 0 we need a page size. Use the minimal size for block 0 here, it will
- * be set to the real value below.
- */
+ // The page size set in mf_open() might be different from the page size
+ // used in the swap file, we must get it from block 0. But to read block
+ // 0 we need a page size. Use the minimal size for block 0 here, it will
+ // be set to the real value below.
mfp->mf_page_size = MIN_SWAP_PAGE_SIZE;
- /*
- * try to read block 0
- */
+ // try to read block 0
if ((hp = mf_get(mfp, 0, 1)) == NULL) {
msg_start();
msg_puts_attr(_("Unable to read block 0 from "), attr | MSG_HIST);
@@ -891,10 +843,8 @@ void ml_recover(bool checkext)
goto theend;
}
- /*
- * If we guessed the wrong page size, we have to recalculate the
- * highest block number in the file.
- */
+ // If we guessed the wrong page size, we have to recalculate the
+ // highest block number in the file.
if (mfp->mf_page_size != (unsigned)char_to_long(b0p->b0_page_size)) {
unsigned previous_page_size = mfp->mf_page_size;
@@ -922,17 +872,15 @@ 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;
}
}
- home_replace(NULL, (char *)mfp->mf_fname, (char *)NameBuff, MAXPATHL, true);
+ home_replace(NULL, mfp->mf_fname, (char *)NameBuff, MAXPATHL, true);
smsg(_("Using swap file \"%s\""), NameBuff);
if (buf_spname(curbuf) != NULL) {
@@ -943,15 +891,13 @@ void ml_recover(bool checkext)
smsg(_("Original file \"%s\""), NameBuff);
msg_putchar('\n');
- /*
- * check date of swap file and original file
- */
+ // check date of swap file and original file
FileInfo org_file_info;
FileInfo swp_file_info;
mtime = char_to_long(b0p->b0_mtime);
if (curbuf->b_ffname != NULL
&& os_fileinfo(curbuf->b_ffname, &org_file_info)
- && ((os_fileinfo((char *)mfp->mf_fname, &swp_file_info)
+ && ((os_fileinfo(mfp->mf_fname, &swp_file_info)
&& org_file_info.stat.st_mtim.tv_sec
> swp_file_info.stat.st_mtim.tv_sec)
|| org_file_info.stat.st_mtim.tv_sec != mtime)) {
@@ -964,25 +910,21 @@ void ml_recover(bool checkext)
if (b0p->b0_flags & B0_HAS_FENC) {
int fnsize = B0_FNAME_SIZE_NOCRYPT;
- for (p = b0p->b0_fname + fnsize; p > b0p->b0_fname && p[-1] != NUL; p--) {}
- b0_fenc = vim_strnsave(p, (size_t)(b0p->b0_fname + fnsize - p));
+ for (p = (char *)b0p->b0_fname + fnsize; (char_u *)p > b0p->b0_fname && p[-1] != NUL; p--) {}
+ b0_fenc = xstrnsave(p, (size_t)(b0p->b0_fname + fnsize - (char_u *)p));
}
mf_put(mfp, hp, false, false); // release block 0
hp = NULL;
- /*
- * Now that we are sure that the file is going to be recovered, clear the
- * contents of the current buffer.
- */
+ // Now that we are sure that the file is going to be recovered, clear the
+ // contents of the current buffer.
while (!(curbuf->b_ml.ml_flags & ML_EMPTY)) {
ml_delete((linenr_T)1, false);
}
- /*
- * Try reading the original file to obtain the values of 'fileformat',
- * 'fileencoding', etc. Ignore errors. The text itself is not used.
- */
+ // Try reading the original file to obtain the values of 'fileformat',
+ // 'fileencoding', etc. Ignore errors. The text itself is not used.
if (curbuf->b_ffname != NULL) {
orig_file_status = readfile(curbuf->b_ffname, NULL, (linenr_T)0,
(linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW, false);
@@ -993,7 +935,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, b0_fenc, OPT_LOCAL);
xfree(b0_fenc);
}
unchanged(curbuf, true, true);
@@ -1019,9 +961,7 @@ void ml_recover(bool checkext)
if (hp != NULL) {
mf_put(mfp, hp, false, false); // release previous block
}
- /*
- * get block
- */
+ // get block
if ((hp = mf_get(mfp, bnum, page_count)) == NULL) {
if (bnum == 1) {
semsg(_("E309: Unable to read block 1 from %s"), mfp->mf_fname);
@@ -1035,7 +975,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) {
@@ -1051,11 +991,9 @@ void ml_recover(bool checkext)
error++;
} else if (idx < (int)pp->pb_count) { // go a block deeper
if (pp->pb_pointer[idx].pe_bnum < 0) {
- /*
- * Data block with negative block number.
- * Try to read lines from the original file.
- * This is slow, but it works.
- */
+ // Data block with negative block number.
+ // Try to read lines from the original file.
+ // This is slow, but it works.
if (!cannot_open) {
line_count = pp->pb_pointer[idx].pe_line_count;
if (readfile(curbuf->b_ffname, NULL, lnum,
@@ -1071,13 +1009,11 @@ 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;
}
- /*
- * going one block deeper in the tree
- */
+ // going one block deeper in the tree
top = ml_add_stack(buf); // new entry in stack
ip = &(buf->b_ml.ml_stack[top]);
ip->ip_bnum = bnum;
@@ -1118,10 +1054,8 @@ void ml_recover(bool checkext)
// make sure there is a NUL at the end of the block
*((char_u *)dp + dp->db_txt_end - 1) = NUL;
- /*
- * check number of lines in block
- * if wrong, use count in data block
- */
+ // check number of lines in block
+ // if wrong, use count in data block
if (line_count != dp->db_line_count) {
ml_append(lnum++,
_("??? from here until ???END lines"
@@ -1131,16 +1065,16 @@ 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) {
- p = (char_u *)"???";
+ p = "???";
error++;
} else {
- p = (char_u *)dp + txt_start;
+ p = (char *)dp + txt_start;
}
- ml_append(lnum++, (char *)p, (colnr_T)0, true);
+ ml_append(lnum++, p, (colnr_T)0, true);
}
if (has_error) {
ml_append(lnum++, _("???END"), (colnr_T)0, true);
@@ -1153,22 +1087,18 @@ void ml_recover(bool checkext)
break;
}
- /*
- * go one block up in the tree
- */
+ // go one block up in the tree
ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]);
bnum = ip->ip_bnum;
idx = ip->ip_index + 1; // go to next index
page_count = 1;
}
- /*
- * Compare the buffer contents with the original file. When they differ
- * set the 'modified' flag.
- * Lines 1 - lnum are the new contents.
- * Lines lnum + 1 to ml_line_count are the original contents.
- * Line ml_line_count + 1 in the dummy empty line.
- */
+ // Compare the buffer contents with the original file. When they differ
+ // set the 'modified' flag.
+ // Lines 1 - lnum are the new contents.
+ // Lines lnum + 1 to ml_line_count are the original contents.
+ // Line ml_line_count + 1 in the dummy empty line.
if (orig_file_status != OK || curbuf->b_ml.ml_line_count != lnum * 2 + 1) {
// Recovering an empty file results in two lines and the first line is
// empty. Don't set the modified flag then.
@@ -1177,10 +1107,10 @@ 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));
+ p = xstrdup(ml_get(idx));
+ i = strcmp(p, ml_get(idx + lnum));
xfree(p);
if (i != 0) {
changed_internal();
@@ -1190,10 +1120,8 @@ void ml_recover(bool checkext)
}
}
- /*
- * Delete the lines from the original file and the dummy line from the
- * empty buffer. These will now be after the last line in the buffer.
- */
+ // Delete the lines from the original file and the dummy line from the
+ // empty buffer. These will now be after the last line in the buffer.
while (curbuf->b_ml.ml_line_count > lnum
&& !(curbuf->b_ml.ml_flags & ML_EMPTY)) {
ml_delete(curbuf->b_ml.ml_line_count, false);
@@ -1201,7 +1129,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,23 +1150,23 @@ 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);
}
mf_close(mfp, false); // will also xfree(mfp->mf_fname)
}
- if (buf != NULL) { //may be NULL if swap file not found.
+ if (buf != NULL) { // may be NULL if swap file not found.
xfree(buf->b_ml.ml_stack);
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,10 +1183,10 @@ 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)
+int recover_names(char_u *fname, int list, int nr, char **fname_out)
{
int num_names;
char *(names[6]);
@@ -1278,7 +1206,7 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
#ifdef HAVE_READLINK
// Expand symlink in the file name, because the swap file is created
// with the actual file instead of with the symlink.
- if (resolve_symlink(fname, fname_buf) == OK) {
+ if (resolve_symlink((char *)fname, (char *)fname_buf) == OK) {
fname_res = fname_buf;
} else
#endif
@@ -1294,7 +1222,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 +1238,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, (char *)fname_res, true);
}
} else { // check directory dir_name
if (fname == NULL) {
@@ -1333,7 +1261,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, (char *)tail, false);
xfree(tail);
}
}
@@ -1345,15 +1273,13 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
num_files = 0;
}
- /*
- * When no swap file found, wildcard expansion might have failed (e.g.
- * not able to execute the shell).
- * Try finding a swap file by simply adding ".swp" to the file name.
- */
+ // When no swap file found, wildcard expansion might have failed (e.g.
+ // not able to execute the shell).
+ // Try finding a swap file by simply adding ".swp" to the file name.
if (*dirp == NUL && file_count + num_files == 0 && fname != NULL) {
char_u *swapname = (char_u *)modname((char *)fname_res, ".swp", true);
if (swapname != NULL) {
- if (os_path_exists(swapname)) {
+ if (os_path_exists((char *)swapname)) {
files = xmalloc(sizeof(char_u *));
files[0] = (char *)swapname;
swapname = NULL;
@@ -1363,11 +1289,9 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
}
}
- /*
- * remove swapfile name of the current buffer, it must be ignored
- */
+ // remove swapfile name of the current buffer, it must be ignored
if (curbuf->b_ml.ml_mfp != NULL
- && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL) {
+ && (p = (char_u *)curbuf->b_ml.ml_mfp->mf_fname) != NULL) {
for (int i = 0; i < num_files; i++) {
// Do not expand wildcards, on Windows would try to expand
// "%tmp%" in "%tmp%file"
@@ -1379,7 +1303,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];
}
}
@@ -1389,7 +1313,7 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
if (nr > 0) {
file_count += num_files;
if (nr <= file_count) {
- *fname_out = vim_strsave((char_u *)files[nr - 1 + num_files - file_count]);
+ *fname_out = xstrdup(files[nr - 1 + num_files - file_count]);
dirp = ""; // stop searching
}
} else if (list) {
@@ -1401,12 +1325,12 @@ int recover_names(char_u *fname, int list, int nr, char_u **fname_out)
}
} else {
msg_puts(_(" In directory "));
- msg_home_replace(dir_name);
+ msg_home_replace((char *)dir_name);
msg_puts(":\n");
}
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 +1346,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 +1371,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);
}
@@ -1524,9 +1448,7 @@ static time_t swapfile_info(char_u *fname)
msg_puts(os_ctime_r(&x, ctime_buf, sizeof(ctime_buf)));
}
- /*
- * print the original file name
- */
+ // print the original file name
fd = os_open((char *)fname, O_RDONLY, 0);
if (fd >= 0) {
if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) {
@@ -1594,7 +1516,7 @@ static bool swapfile_unchanged(char *fname)
int ret = true;
// Swap file must exist.
- if (!os_path_exists((char_u *)fname)) {
+ if (!os_path_exists(fname)) {
return false;
}
@@ -1631,7 +1553,7 @@ static bool swapfile_unchanged(char *fname)
return ret;
}
-static int recov_file_names(char **names, char_u *path, int prepend_dot)
+static int recov_file_names(char **names, char *path, int prepend_dot)
FUNC_ATTR_NONNULL_ALL
{
int num_names = 0;
@@ -1639,7 +1561,7 @@ static int recov_file_names(char **names, char_u *path, int prepend_dot)
// May also add the file name with a dot prepended, for swap file in same
// dir as original file.
if (prepend_dot) {
- names[num_names] = modname((char *)path, ".sw?", true);
+ names[num_names] = modname(path, ".sw?", true);
if (names[num_names] == NULL) {
return num_names;
}
@@ -1647,14 +1569,14 @@ static int recov_file_names(char **names, char_u *path, int prepend_dot)
}
// Form the normal swap file name pattern by appending ".sw?".
- names[num_names] = concat_fnames((char *)path, ".sw?", false);
+ names[num_names] = concat_fnames(path, ".sw?", false);
if (num_names >= 1) { // check if we have the same name twice
- char_u *p = (char_u *)names[num_names - 1];
+ char *p = names[num_names - 1];
int i = (int)STRLEN(names[num_names - 1]) - (int)STRLEN(names[num_names]);
if (i > 0) {
p += i; // file name has been expanded to full path
}
- if (STRCMP(p, names[num_names]) != 0) {
+ if (strcmp(p, names[num_names]) != 0) {
num_names++;
} else {
xfree(names[num_names]);
@@ -1668,8 +1590,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)
@@ -1683,10 +1605,8 @@ void ml_sync_all(int check_file, int check_char, bool do_fsync)
(void)ml_find_line(buf, (linenr_T)0, ML_FLUSH);
if (bufIsChanged(buf) && check_file && mf_need_trans(buf->b_ml.ml_mfp)
&& buf->b_ffname != NULL) {
- /*
- * If the original file does not exist anymore or has been changed
- * call ml_preserve() to get rid of all negative numbered blocks.
- */
+ // If the original file does not exist anymore or has been changed
+ // call ml_preserve() to get rid of all negative numbered blocks.
FileInfo file_info;
if (!os_fileinfo(buf->b_ffname, &file_info)
|| file_info.stat.st_mtim.tv_sec != buf->b_mtime_read
@@ -1714,7 +1634,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;
@@ -1741,18 +1661,16 @@ void ml_preserve(buf_T *buf, int message, bool do_fsync)
// stack is invalid after mf_sync(.., MFS_ALL)
buf->b_ml.ml_stack_top = 0;
- /*
- * Some of the data blocks may have been changed from negative to
- * positive block number. In that case the pointer blocks need to be
- * updated.
- *
- * We don't know in which pointer block the references are, so we visit
- * all data blocks until there are no more translations to be done (or
- * we hit the end of the file, which can only happen in case a write fails,
- * e.g. when file system if full).
- * ml_find_line() does the work by translating the negative block numbers
- * when getting the first line of each data block.
- */
+ // Some of the data blocks may have been changed from negative to
+ // positive block number. In that case the pointer blocks need to be
+ // updated.
+ //
+ // We don't know in which pointer block the references are, so we visit
+ // all data blocks until there are no more translations to be done (or
+ // we hit the end of the file, which can only happen in case a write fails,
+ // e.g. when file system if full).
+ // ml_find_line() does the work by translating the negative block numbers
+ // when getting the first line of each data block.
if (mf_need_trans(mfp) && !got_int) {
lnum = 1;
while (mf_need_trans(mfp) && lnum <= buf->b_ml.ml_line_count) {
@@ -1783,19 +1701,17 @@ theend:
}
}
-/*
- * NOTE: The pointer returned by the ml_get_*() functions only remains valid
- * until the next call!
- * line1 = ml_get(1);
- * line2 = ml_get(2); // line1 is now invalid!
- * Make a copy of the line if necessary.
- */
+// NOTE: The pointer returned by the ml_get_*() functions only remains valid
+// until the next call!
+// line1 = ml_get(1);
+// line2 = ml_get(2); // line1 is now invalid!
+// Make a copy of the line if necessary.
/// @return a pointer to a (read-only copy of a) line.
///
/// On failure an error message is given and IObuff is returned (to avoid
/// having to check for error everywhere).
-char_u *ml_get(linenr_T lnum)
+char *ml_get(linenr_T lnum)
{
return ml_get_buf(curbuf, lnum, false);
}
@@ -1804,7 +1720,7 @@ char_u *ml_get(linenr_T lnum)
char_u *ml_get_pos(const pos_T *pos)
FUNC_ATTR_NONNULL_ALL
{
- return ml_get_buf(curbuf, pos->lnum, false) + pos->col;
+ return (char_u *)ml_get_buf(curbuf, pos->lnum, false) + pos->col;
}
/// @return codepoint at pos. pos must be either valid or have col set to MAXCOL!
@@ -1821,14 +1737,14 @@ int gchar_pos(pos_T *pos)
/// @param will_change true mark the buffer dirty (chars in the line will be changed)
///
/// @return a pointer to a line in a specific buffer
-char_u *ml_get_buf(buf_T *buf, linenr_T lnum, bool will_change)
+char *ml_get_buf(buf_T *buf, linenr_T lnum, bool will_change)
FUNC_ATTR_NONNULL_ALL
{
bhdr_T *hp;
DATA_BL *dp;
- char_u *ptr;
+ char *ptr;
static int recursive = 0;
- static char_u questions[4];
+ static char questions[4];
if (lnum > buf->b_ml.ml_line_count) { // invalid line number
if (recursive == 0) {
@@ -1850,23 +1766,19 @@ errorret:
}
if (buf->b_ml.ml_mfp == NULL) { // there are no lines
- return (char_u *)"";
+ return "";
}
- /*
- * See if it is the same line as requested last time.
- * Otherwise may need to flush last used line.
- * Don't use the last used line when 'swapfile' is reset, need to load all
- * blocks.
- */
+ // See if it is the same line as requested last time.
+ // Otherwise may need to flush last used line.
+ // Don't use the last used line when 'swapfile' is reset, need to load all
+ // blocks.
if (buf->b_ml.ml_line_lnum != lnum) {
ml_flush_line(buf);
- /*
- * Find the data block containing the line.
- * This also fills the stack with the blocks from the root to the data
- * block and releases any locked block.
- */
+ // Find the data block containing the line.
+ // This also fills the stack with the blocks from the root to the data
+ // block and releases any locked block.
if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL) {
if (recursive == 0) {
// Avoid giving this message for a recursive call, may happen
@@ -1883,9 +1795,9 @@ errorret:
dp = hp->bh_data;
- ptr = (char_u *)dp +
+ ptr = (char *)dp +
((dp->db_index[lnum - buf->b_ml.ml_locked_low]) & DB_INDEX_MASK);
- buf->b_ml.ml_line_ptr = ptr;
+ buf->b_ml.ml_line_ptr = (char_u *)ptr;
buf->b_ml.ml_line_lnum = lnum;
buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
}
@@ -1894,7 +1806,7 @@ errorret:
ml_add_deleted_len_buf(buf, buf->b_ml.ml_line_ptr, -1);
}
- return buf->b_ml.ml_line_ptr;
+ return (char *)buf->b_ml.ml_line_ptr;
}
/// Check if a line that was just obtained by a call to ml_get
@@ -1908,7 +1820,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 +1834,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 +1861,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)
@@ -1988,11 +1900,9 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
memfile_T *mfp = buf->b_ml.ml_mfp;
int page_size = (int)mfp->mf_page_size;
- /*
- * find the data block containing the previous line
- * This also fills the stack with the blocks from the root to the data block
- * This also releases any locked block.
- */
+ // find the data block containing the previous line
+ // This also fills the stack with the blocks from the root to the data block
+ // This also releases any locked block.
if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_T)1 : lnum,
ML_INSERT)) == NULL) {
return FAIL;
@@ -2010,22 +1920,18 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
dp = hp->bh_data;
- /*
- * If
- * - there is not enough room in the current block
- * - appending to the last line in the block
- * - not appending to the last line in the file
- * insert in front of the next block.
- */
+ // If
+ // - there is not enough room in the current block
+ // - appending to the last line in the block
+ // - not appending to the last line in the file
+ // insert in front of the next block.
if ((int)dp->db_free < space_needed && db_idx == line_count - 1
&& lnum < buf->b_ml.ml_line_count) {
- /*
- * Now that the line is not going to be inserted in the block that we
- * expected, the line count has to be adjusted in the pointer blocks
- * by using ml_locked_lineadd.
- */
- --(buf->b_ml.ml_locked_lineadd);
- --(buf->b_ml.ml_locked_high);
+ // Now that the line is not going to be inserted in the block that we
+ // expected, the line count has to be adjusted in the pointer blocks
+ // by using ml_locked_lineadd.
+ (buf->b_ml.ml_locked_lineadd)--;
+ (buf->b_ml.ml_locked_high)--;
if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL) {
return FAIL;
}
@@ -2038,25 +1944,19 @@ 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
- /*
- * Insert new line in existing data block, or in data block allocated above.
- */
+ // Insert new line in existing data block, or in data block allocated above.
dp->db_txt_start -= (unsigned)len;
dp->db_free -= (unsigned)space_needed;
dp->db_line_count++;
- /*
- * move the text of the lines that follow to the front
- * adjust the indexes of the lines that follow
- */
+ // move the text of the lines that follow to the front
+ // adjust the indexes of the lines that follow
if (line_count > db_idx + 1) { // if there are following lines
- /*
- * Offset is the start of the previous line.
- * This will become the character just after the new line.
- */
+ // Offset is the start of the previous line.
+ // This will become the character just after the new line.
if (db_idx < 0) {
offset = (int)dp->db_txt_end;
} else {
@@ -2073,31 +1973,25 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
dp->db_index[db_idx + 1] = dp->db_txt_start;
}
- /*
- * copy the text into the block
- */
+ // copy the text into the block
memmove((char *)dp + dp->db_index[db_idx + 1], line, (size_t)len);
if (mark) {
dp->db_index[db_idx + 1] |= DB_MARKED;
}
- /*
- * Mark the block dirty.
- */
+ // Mark the block dirty.
buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
if (!newfile) {
buf->b_ml.ml_flags |= ML_LOCKED_POS;
}
} else { // not enough space in data block
- /*
- * If there is not enough room we have to create a new data block and copy some
- * lines into it.
- * Then we have to insert an entry in the pointer block.
- * If this pointer block also is full, we go up another block, and so on, up
- * to the root if necessary.
- * The line counts in the pointer blocks have already been adjusted by
- * ml_find_line().
- */
+ // If there is not enough room we have to create a new data block and copy some
+ // lines into it.
+ // Then we have to insert an entry in the pointer block.
+ // If this pointer block also is full, we go up another block, and so on, up
+ // to the root if necessary.
+ // The line counts in the pointer blocks have already been adjusted by
+ // ml_find_line().
int line_count_left, line_count_right;
int page_count_left, page_count_right;
bhdr_T *hp_left;
@@ -2115,14 +2009,12 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
int pb_idx;
PTR_BL *pp_new;
- /*
- * We are going to allocate a new data block. Depending on the
- * situation it will be put to the left or right of the existing
- * block. If possible we put the new line in the left block and move
- * the lines after it to the right block. Otherwise the new line is
- * also put in the right block. This method is more efficient when
- * inserting a lot of lines at one place.
- */
+ // We are going to allocate a new data block. Depending on the
+ // situation it will be put to the left or right of the existing
+ // block. If possible we put the new line in the left block and move
+ // the lines after it to the right block. Otherwise the new line is
+ // also put in the right block. This method is more efficient when
+ // inserting a lot of lines at one place.
if (db_idx < 0) { // left block is new, right block is existing
lines_moved = 0;
in_left = true;
@@ -2166,9 +2058,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
page_count_left = (int)hp_left->bh_page_count;
page_count_right = (int)hp_right->bh_page_count;
- /*
- * May move the new line into the right/new block.
- */
+ // May move the new line into the right/new block.
if (!in_left) {
dp_right->db_txt_start -= (unsigned)len;
dp_right->db_free -= (unsigned)len + (unsigned)INDEX_SIZE;
@@ -2181,12 +2071,8 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
line, (size_t)len);
line_count_right++;
}
- /*
- * may move lines from the left/old block to the right/new one.
- */
+ // may move lines from the left/old block to the right/new one.
if (lines_moved) {
- /*
- */
dp_right->db_txt_start -= (unsigned)data_moved;
dp_right->db_free -= (unsigned)total_moved;
memmove((char *)dp_right + dp_right->db_txt_start,
@@ -2196,9 +2082,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
dp_left->db_txt_start += (unsigned)data_moved;
dp_left->db_free += (unsigned)total_moved;
- /*
- * update indexes in the new block
- */
+ // update indexes in the new block
for (to = line_count_right, from = db_idx + 1;
from < line_count_left; from++, to++) {
dp_right->db_index[to] = dp->db_index[from] + (unsigned)offset;
@@ -2207,9 +2091,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
line_count_left -= lines_moved;
}
- /*
- * May move the new line into the left (old or new) block.
- */
+ // May move the new line into the left (old or new) block.
if (in_left) {
dp_left->db_txt_start -= (unsigned)len;
dp_left->db_free -= (unsigned)len + (unsigned)INDEX_SIZE;
@@ -2236,12 +2118,10 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
dp_left->db_line_count = line_count_left;
dp_right->db_line_count = line_count_right;
- /*
- * release the two data blocks
- * The new one (hp_new) already has a correct blocknumber.
- * The old one (hp, in ml_locked) gets a positive blocknumber if
- * we changed it and we are not editing a new file.
- */
+ // release the two data blocks
+ // The new one (hp_new) already has a correct blocknumber.
+ // The old one (hp, in ml_locked) gets a positive blocknumber if
+ // we changed it and we are not editing a new file.
if (lines_moved || in_left) {
buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
}
@@ -2250,18 +2130,14 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
}
mf_put(mfp, hp_new, true, false);
- /*
- * flush the old data block
- * set ml_locked_lineadd to 0, because the updating of the
- * pointer blocks is done below
- */
+ // flush the old data block
+ // set ml_locked_lineadd to 0, because the updating of the
+ // pointer blocks is done below
lineadd = buf->b_ml.ml_locked_lineadd;
buf->b_ml.ml_locked_lineadd = 0;
(void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); // flush data block
- /*
- * update pointer blocks for the new data block
- */
+ // update pointer blocks for the new data block
for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0;
--stack_idx) {
ip = &(buf->b_ml.ml_stack[stack_idx]);
@@ -2275,10 +2151,8 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
mf_put(mfp, hp, false, false);
return FAIL;
}
- /*
- * TODO: If the pointer block is full and we are adding at the end
- * try to insert in front of the next block
- */
+ // TODO(vim): If the pointer block is full and we are adding at the end
+ // try to insert in front of the next block
// block not full, add one entry
if (pp->pb_count < pp->pb_count_max) {
if (pb_idx + 1 < (int)pp->pb_count) {
@@ -2286,7 +2160,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;
@@ -2314,9 +2188,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
++(buf->b_ml.ml_stack_top);
}
- /*
- * We are finished, break the loop here.
- */
+ // We are finished, break the loop here.
break;
}
// pointer block full
@@ -2402,9 +2274,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
mf_put(mfp, hp_new, true, false);
}
- /*
- * Safety check: fallen out of for loop?
- */
+ // Safety check: fallen out of for loop?
if (stack_idx < 0) {
iemsg(_("E318: Updated too many blocks?"));
buf->b_ml.ml_stack_top = 0; // invalidate stack
@@ -2416,9 +2286,9 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
return OK;
}
-void ml_add_deleted_len(char_u *ptr, ssize_t len)
+void ml_add_deleted_len(char *ptr, ssize_t len)
{
- ml_add_deleted_len_buf(curbuf, ptr, len);
+ ml_add_deleted_len_buf(curbuf, (char_u *)ptr, len);
}
void ml_add_deleted_len_buf(buf_T *buf, char_u *ptr, ssize_t len)
@@ -2441,7 +2311,7 @@ void ml_add_deleted_len_buf(buf_T *buf, char_u *ptr, ssize_t len)
int ml_replace(linenr_T lnum, char *line, bool copy)
{
- return ml_replace_buf(curbuf, lnum, (char_u *)line, copy);
+ return ml_replace_buf(curbuf, lnum, line, copy);
}
/// Replace line "lnum", with buffering, in current buffer.
@@ -2453,10 +2323,10 @@ 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)
+int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy)
{
if (line == NULL) { // just checking...
return FAIL;
@@ -2470,7 +2340,7 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char_u *line, bool copy)
bool readlen = true;
if (copy) {
- line = vim_strsave(line);
+ line = xstrdup(line);
}
if (buf->b_ml.ml_line_lnum != lnum) { // other line buffered
ml_flush_line(buf); // flush it
@@ -2482,10 +2352,10 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char_u *line, bool copy)
}
if (readlen && kv_size(buf->update_callbacks)) {
- ml_add_deleted_len_buf(buf, ml_get_buf(buf, lnum, false), -1);
+ ml_add_deleted_len_buf(buf, (char_u *)ml_get_buf(buf, lnum, false), -1);
}
- buf->b_ml.ml_line_ptr = line;
+ buf->b_ml.ml_line_ptr = (char_u *)line;
buf->b_ml.ml_line_lnum = lnum;
buf->b_ml.ml_flags = (buf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
@@ -2528,9 +2398,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message)
lowest_marked--;
}
- /*
- * If the file becomes empty the last line is replaced by an empty line.
- */
+ // If the file becomes empty the last line is replaced by an empty line.
if (buf->b_ml.ml_line_count == 1) { // file becomes empty
if (message) {
set_keep_msg(_(no_lines_msg), 0);
@@ -2542,11 +2410,9 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message)
return i;
}
- /*
- * find the data block containing the line
- * This also fills the stack with the blocks from the root to the data block
- * This also releases any locked block.
- */
+ // find the data block containing the line
+ // This also fills the stack with the blocks from the root to the data block
+ // This also releases any locked block.
mfp = buf->b_ml.ml_mfp;
if (mfp == NULL) {
return FAIL;
@@ -2561,7 +2427,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
@@ -2575,14 +2441,12 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message)
assert(line_size >= 1);
ml_add_deleted_len_buf(buf, (char_u *)dp + line_start, line_size - 1);
- /*
- * special case: If there is only one line in the data block it becomes empty.
- * Then we have to remove the entry, pointing to this data block, from the
- * pointer block. If this pointer block also becomes empty, we go up another
- * block, and so on, up to the root if necessary.
- * The line counts in the pointer blocks have already been adjusted by
- * ml_find_line().
- */
+ // special case: If there is only one line in the data block it becomes empty.
+ // Then we have to remove the entry, pointing to this data block, from the
+ // pointer block. If this pointer block also becomes empty, we go up another
+ // block, and so on, up to the root if necessary.
+ // The line counts in the pointer blocks have already been adjusted by
+ // ml_find_line().
if (count == 1) {
mf_free(mfp, hp); // free the data block
buf->b_ml.ml_locked = NULL;
@@ -2640,9 +2504,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message)
dp->db_txt_start += (unsigned)line_size;
dp->db_line_count--;
- /*
- * mark the block dirty and make sure it is in the file (for recovery)
- */
+ // mark the block dirty and make sure it is in the file (for recovery)
buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
}
@@ -2664,11 +2526,9 @@ void ml_setmarked(linenr_T lnum)
lowest_marked = lnum;
}
- /*
- * find the data block containing the line
- * This also fills the stack with the blocks from the root to the data block
- * This also releases any locked block.
- */
+ // find the data block containing the line
+ // This also fills the stack with the blocks from the root to the data block
+ // This also releases any locked block.
if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) {
return; // give error message?
}
@@ -2689,23 +2549,19 @@ linenr_T ml_firstmarked(void)
return (linenr_T)0;
}
- /*
- * The search starts with lowest_marked line. This is the last line where
- * a mark was found, adjusted by inserting/deleting lines.
- */
+ // The search starts with lowest_marked line. This is the last line where
+ // a mark was found, adjusted by inserting/deleting lines.
for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) {
- /*
- * Find the data block containing the line.
- * This also fills the stack with the blocks from the root to the data
- * block This also releases any locked block.
- */
+ // Find the data block containing the line.
+ // This also fills the stack with the blocks from the root to the data
+ // block This also releases any locked block.
if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) {
return (linenr_T)0; // give error message?
}
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;
@@ -2730,22 +2586,18 @@ void ml_clearmarked(void)
return;
}
- /*
- * The search starts with line lowest_marked.
- */
+ // The search starts with line lowest_marked.
for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) {
- /*
- * Find the data block containing the line.
- * This also fills the stack with the blocks from the root to the data
- * block and releases any locked block.
- */
+ // Find the data block containing the line.
+ // This also fills the stack with the blocks from the root to the data
+ // block and releases any locked block.
if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) {
return; // give error message?
}
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;
@@ -2815,9 +2667,7 @@ static void ml_flush_line(buf_T *buf)
new_len = (colnr_T)STRLEN(new_line) + 1;
extra = new_len - old_len; // negative if lines gets smaller
- /*
- * if new line fits in data block, replace directly
- */
+ // if new line fits in data block, replace directly
if ((int)dp->db_free >= extra) {
// if the length changes and there are following lines
count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1;
@@ -2920,13 +2770,11 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
mfp = buf->b_ml.ml_mfp;
- /*
- * If there is a locked block check if the wanted line is in it.
- * If not, flush and release the locked block.
- * Don't do this for ML_INSERT_SAME, because the stack need to be updated.
- * Don't do this for ML_FLUSH, because we want to flush the locked block.
- * Don't do this when 'swapfile' is reset, we want to load all the blocks.
- */
+ // If there is a locked block check if the wanted line is in it.
+ // If not, flush and release the locked block.
+ // Don't do this for ML_INSERT_SAME, because the stack need to be updated.
+ // Don't do this for ML_FLUSH, because we want to flush the locked block.
+ // Don't do this when 'swapfile' is reset, we want to load all the blocks.
if (buf->b_ml.ml_locked) {
if (ML_SIMPLE(action)
&& buf->b_ml.ml_locked_low <= lnum
@@ -2946,10 +2794,8 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
buf->b_ml.ml_flags & ML_LOCKED_POS);
buf->b_ml.ml_locked = NULL;
- /*
- * If lines have been added or deleted in the locked block, need to
- * update the line count in pointer blocks.
- */
+ // If lines have been added or deleted in the locked block, need to
+ // update the line count in pointer blocks.
if (buf->b_ml.ml_locked_lineadd != 0) {
ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
}
@@ -2965,7 +2811,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;
@@ -2981,17 +2827,13 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
} else { // ML_DELETE or ML_INSERT
buf->b_ml.ml_stack_top = 0; // start at the root
}
- /*
- * search downwards in the tree until a data block is found
- */
+ // search downwards in the tree until a data block is found
for (;;) {
if ((hp = mf_get(mfp, bnum, (unsigned)page_count)) == NULL) {
goto error_noblock;
}
- /*
- * update high for insert/delete
- */
+ // update high for insert/delete
if (action == ML_INSERT) {
high++;
} else if (action == ML_DELETE) {
@@ -3021,8 +2863,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) {
@@ -3032,15 +2874,13 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
high = low - 1;
low -= t;
- /*
- * a negative block number may have been changed
- */
+ // a negative block number may have been changed
if (bnum < 0) {
bnum2 = mf_trans_del(mfp, bnum);
if (bnum != bnum2) {
bnum = bnum2;
pp->pb_pointer[idx].pe_bnum = bnum;
- dirty = TRUE;
+ dirty = true;
}
}
@@ -3058,10 +2898,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);
}
@@ -3069,11 +2909,9 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
error_block:
mf_put(mfp, hp, false, false);
error_noblock:
- /*
- * If action is ML_DELETE or ML_INSERT we have to correct the tree for
- * the incremented/decremented line counts, because there won't be a line
- * inserted/deleted after all.
- */
+ // If action is ML_DELETE or ML_INSERT we have to correct the tree for
+ // the incremented/decremented line counts, because there won't be a line
+ // inserted/deleted after all.
if (action == ML_DELETE) {
ml_lineadd(buf, 1);
} else if (action == ML_INSERT) {
@@ -3119,7 +2957,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;
@@ -3144,9 +2982,9 @@ static void ml_lineadd(buf_T *buf, int count)
///
/// @return OK if it worked and the resolved link in "buf[MAXPATHL]",
/// FAIL otherwise
-int resolve_symlink(const char_u *fname, char_u *buf)
+int resolve_symlink(const char *fname, char *buf)
{
- char_u tmp[MAXPATHL];
+ char tmp[MAXPATHL];
int ret;
int depth = 0;
@@ -3164,7 +3002,7 @@ int resolve_symlink(const char_u *fname, char_u *buf)
return FAIL;
}
- ret = (int)readlink((char *)tmp, (char *)buf, MAXPATHL - 1);
+ ret = (int)readlink(tmp, buf, MAXPATHL - 1);
if (ret <= 0) {
if (errno == EINVAL || errno == ENOENT) {
// Found non-symlink or not existing file, stop here.
@@ -3187,10 +3025,10 @@ int resolve_symlink(const char_u *fname, char_u *buf)
// If it's relative, build a new path based on the directory
// portion of the filename (if any) and the path the symlink
// points to.
- if (path_is_absolute(buf)) {
+ if (path_is_absolute((char_u *)buf)) {
STRCPY(tmp, buf);
} else {
- char_u *tail = (char_u *)path_tail((char *)tmp);
+ char_u *tail = (char_u *)path_tail(tmp);
if (STRLEN(tail) + STRLEN(buf) >= MAXPATHL) {
return FAIL;
}
@@ -3198,12 +3036,10 @@ int resolve_symlink(const char_u *fname, char_u *buf)
}
}
- /*
- * Try to resolve the full name of the file so that the swapfile name will
- * be consistent even when opening a relative symlink from different
- * working directories.
- */
- return vim_FullName((char *)tmp, (char *)buf, MAXPATHL, TRUE);
+ // Try to resolve the full name of the file so that the swapfile name will
+ // be consistent even when opening a relative symlink from different
+ // working directories.
+ return vim_FullName(tmp, buf, MAXPATHL, true);
}
#endif
@@ -3219,7 +3055,7 @@ char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name
// Expand symlink in the file name, so that we put the swap file with the
// actual file instead of with the symlink.
- if (resolve_symlink(fname, fname_buf) == OK) {
+ if (resolve_symlink((char *)fname, (char *)fname_buf) == OK) {
fname_res = fname_buf;
}
#endif
@@ -3245,7 +3081,7 @@ char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name
return NULL;
}
- s = get_file_in_dir(r, dir_name);
+ s = (char_u *)get_file_in_dir((char *)r, (char *)dir_name);
xfree(r);
return s;
}
@@ -3262,30 +3098,30 @@ char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name
/// The return value is an allocated string and can be NULL.
///
/// @param dname don't use "dirname", it is a global for Alpha
-char_u *get_file_in_dir(char_u *fname, char_u *dname)
+char *get_file_in_dir(char *fname, char *dname)
{
- char_u *t;
- char_u *tail;
- char_u *retval;
+ char *t;
+ char *tail;
+ char *retval;
int save_char;
- tail = (char_u *)path_tail((char *)fname);
+ tail = path_tail(fname);
if (dname[0] == '.' && dname[1] == NUL) {
- retval = vim_strsave(fname);
+ retval = xstrdup(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 = concat_fnames(dname + 2, tail, true);
} else {
- save_char = *tail;
+ save_char = (uint8_t)(*tail);
*tail = NUL;
- t = (char_u *)concat_fnames((char *)fname, (char *)dname + 2, true);
- *tail = (uint8_t)save_char;
- retval = (char_u *)concat_fnames((char *)t, (char *)tail, true);
+ t = concat_fnames(fname, dname + 2, true);
+ *tail = (char)save_char;
+ retval = concat_fnames(t, tail, true);
xfree(t);
}
} else {
- retval = (char_u *)concat_fnames((char *)dname, (char *)tail, TRUE);
+ retval = concat_fnames(dname, tail, true);
}
return retval;
@@ -3302,7 +3138,7 @@ static void attention_message(buf_T *buf, char_u *fname)
no_wait_return++;
(void)emsg(_("E325: ATTENTION"));
msg_puts(_("\nFound a swap file by the name \""));
- msg_home_replace(fname);
+ msg_home_replace((char *)fname);
msg_puts("\"\n");
const time_t swap_mtime = swapfile_info(fname);
msg_puts(_("While opening file \""));
@@ -3409,17 +3245,13 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
char *dir_name;
char *buf_fname = buf->b_fname;
- /*
- * Isolate a directory name from *dirp and put it in dir_name.
- * First allocate some memory to put the directory name in.
- */
+ // Isolate a directory name from *dirp and put it in dir_name.
+ // First allocate some memory to put the directory name in.
const size_t dir_len = strlen(*dirp) + 1;
dir_name = xmalloc(dir_len);
(void)copy_option_part(dirp, dir_name, dir_len, ",");
- /*
- * we try different names until we find one that does not exist yet
- */
+ // we try different names until we find one that does not exist yet
fname = (char *)makeswapname((char_u *)buf_fname, (char_u *)buf->b_ffname, buf,
(char_u *)dir_name);
@@ -3441,7 +3273,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
}
// A file name equal to old_fname is OK to use.
- if (old_fname != NULL && FNAMECMP(fname, old_fname) == 0) {
+ if (old_fname != NULL && path_fnamecmp(fname, old_fname) == 0) {
break;
}
@@ -3455,7 +3287,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).
@@ -3466,25 +3298,25 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
// buffer don't compare the directory names, they can
// have a different mountpoint.
if (b0.b0_flags & B0_SAME_DIR) {
- if (FNAMECMP(path_tail((char *)buf->b_ffname),
- path_tail((char *)b0.b0_fname)) != 0
+ if (path_fnamecmp(path_tail(buf->b_ffname),
+ path_tail((char *)b0.b0_fname)) != 0
|| !same_directory((char_u *)fname, (char_u *)buf->b_ffname)) {
// 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(buf->b_ffname, 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(buf->b_ffname, NameBuff,
char_to_long(b0.b0_ino))) {
- differ = TRUE;
+ differ = true;
}
}
}
@@ -3494,14 +3326,14 @@ 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;
// It's safe to delete the swap file if all these are true:
// - the edited file exists
// - the swap file has no changes and looks OK
- if (os_path_exists((char_u *)buf->b_fname) && swapfile_unchanged(fname)) {
+ if (os_path_exists(buf->b_fname) && swapfile_unchanged(fname)) {
choice = 4;
if (p_verbose > 0) {
verb_msg(_("Found a swap file that is not useful, deleting it"));
@@ -3543,13 +3375,13 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
memcpy(name, sw_msg_1, sw_msg_1_len + 1);
home_replace(NULL, fname, &name[sw_msg_1_len], fname_len, true);
xstrlcat(name, sw_msg_2, name_len);
- choice = do_dialog(VIM_WARNING, (char_u *)_("VIM - ATTENTION"),
- (char_u *)name,
+ choice = do_dialog(VIM_WARNING, _("VIM - ATTENTION"),
+ name,
process_still_running
- ? (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover"
- "\n&Quit\n&Abort") :
- (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover"
- "\n&Delete it\n&Quit\n&Abort"),
+ ? _("&Open Read-Only\n&Edit anyway\n&Recover"
+ "\n&Quit\n&Abort") :
+ _("&Open Read-Only\n&Edit anyway\n&Recover"
+ "\n&Delete it\n&Quit\n&Abort"),
1, NULL, false);
if (process_still_running && choice >= 4) {
@@ -3564,7 +3396,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,12 +3411,12 @@ 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;
}
// If the file was deleted this fname can be used.
- if (!os_path_exists((char_u *)fname)) {
+ if (!os_path_exists(fname)) {
break;
}
} else {
@@ -3598,25 +3430,23 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
}
}
- /*
- * Change the ".swp" extension to find another file that can be used.
- * First decrement the last char: ".swo", ".swn", etc.
- * If that still isn't enough decrement the last but one char: ".svz"
- * Can happen when editing many "No Name" buffers.
- */
+ // Change the ".swp" extension to find another file that can be used.
+ // First decrement the last char: ".swo", ".swn", etc.
+ // If that still isn't enough decrement the last but one char: ".svz"
+ // Can happen when editing many "No Name" buffers.
if (fname[n - 1] == 'a') { // ".s?a"
if (fname[n - 2] == 'a') { // ".saa": tried enough, give up
emsg(_("E326: Too many swap files 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 +3497,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
@@ -3689,26 +3519,24 @@ static int b0_magic_wrong(ZERO_BL *b0p)
///
/// @param fname_c current file name
/// @param fname_s file name from swap file
-static bool fnamecmp_ino(char_u *fname_c, char_u *fname_s, long ino_block0)
+static bool fnamecmp_ino(char *fname_c, char *fname_s, long ino_block0)
{
uint64_t ino_c = 0; // ino of current file
uint64_t ino_s; // ino of file from swap file
- char_u buf_c[MAXPATHL]; // full path of fname_c
- char_u buf_s[MAXPATHL]; // full path of fname_s
+ char buf_c[MAXPATHL]; // full path of fname_c
+ char buf_s[MAXPATHL]; // full path of fname_s
int retval_c; // flag: buf_c valid
int retval_s; // flag: buf_s valid
FileInfo file_info;
- if (os_fileinfo((char *)fname_c, &file_info)) {
+ if (os_fileinfo(fname_c, &file_info)) {
ino_c = os_fileinfo_inode(&file_info);
}
- /*
- * First we try to get the inode from the file name, because the inode in
- * the swap file may be outdated. If that fails (e.g. this path is not
- * valid on this machine), use the inode from block 0.
- */
- if (os_fileinfo((char *)fname_s, &file_info)) {
+ // First we try to get the inode from the file name, because the inode in
+ // the swap file may be outdated. If that fails (e.g. this path is not
+ // valid on this machine), use the inode from block 0.
+ if (os_fileinfo(fname_s, &file_info)) {
ino_s = os_fileinfo_inode(&file_info);
} else {
ino_s = (uint64_t)ino_block0;
@@ -3718,23 +3546,19 @@ static bool fnamecmp_ino(char_u *fname_c, char_u *fname_s, long ino_block0)
return ino_c != ino_s;
}
- /*
- * 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);
+ // One of the inode numbers is unknown, try a forced vim_FullName() and
+ // compare the file names.
+ retval_c = vim_FullName(fname_c, (char *)buf_c, MAXPATHL, true);
+ retval_s = vim_FullName(fname_s, (char *)buf_s, MAXPATHL, true);
if (retval_c == OK && retval_s == OK) {
- return STRCMP(buf_c, buf_s) != 0;
+ return strcmp(buf_c, buf_s) != 0;
}
- /*
- * Can't compare inodes or file names, guess that the files are different,
- * unless both appear not to exist at all, then compare with the file name
- * in the swap file.
- */
+ // Can't compare inodes or file names, guess that the files are different,
+ // unless both appear not to exist at all, then compare with the file name
+ // in the swap file.
if (ino_s == 0 && ino_c == 0 && retval_c == FAIL && retval_s == FAIL) {
- return STRCMP(fname_c, fname_s) != 0;
+ return strcmp(fname_c, fname_s) != 0;
}
return true;
}
@@ -3829,9 +3653,7 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, long len, int updtype)
}
if (updtype == ML_CHNK_UPDLINE && buf->b_ml.ml_line_count == 1) {
- /*
- * First line in empty buffer from ml_flush_line() -- reset
- */
+ // First line in empty buffer from ml_flush_line() -- reset
buf->b_ml.ml_usedchunks = 1;
buf->b_ml.ml_chunksize[0].mlcs_numlines = 1;
buf->b_ml.ml_chunksize[0].mlcs_totalsize =
@@ -3839,10 +3661,8 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, long len, int updtype)
return;
}
- /*
- * Find chunk that our line belongs to, curline will be at start of the
- * chunk.
- */
+ // Find chunk that our line belongs to, curline will be at start of the
+ // chunk.
if (buf != ml_upd_lastbuf || line != ml_upd_lastline + 1
|| updtype != ML_CHNK_ADDLINE) {
for (curline = 1, curix = 0;
@@ -3930,10 +3750,8 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, long len, int updtype)
curchnk->mlcs_numlines = 0;
curchnk->mlcs_totalsize = 0;
} else {
- /*
- * Line is just prior to last, move count for last
- * This is the common case when loading a new file
- */
+ // Line is just prior to last, move count for last
+ // This is the common case when loading a new file
hp = ml_find_line(buf, buf->b_ml.ml_line_count, ML_FIND);
if (hp == NULL) {
buf->b_ml.ml_usedchunks = -1;
@@ -4046,10 +3864,8 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp, bool no_ff)
if (lnum == 0 && offset <= 0) {
return 1; // Not a "find offset" and offset 0 _must_ be in line 1
}
- /*
- * Find the last chunk before the one containing our line. Last chunk is
- * special because it will never qualify
- */
+ // Find the last chunk before the one containing our line. Last chunk is
+ // special because it will never qualify
curline = 1;
curix = 0;
size = 0;
@@ -4163,7 +3979,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();
@@ -4214,8 +4030,8 @@ int dec(pos_T *lp)
lp->coladd = 0;
if (lp->col == MAXCOL) {
// past end of line
- char_u *p = ml_get(lp->lnum);
- lp->col = (colnr_T)STRLEN(p);
+ char *p = ml_get(lp->lnum);
+ lp->col = (colnr_T)strlen(p);
lp->col -= utf_head_off(p, p + lp->col);
return 0;
}
@@ -4223,15 +4039,15 @@ int dec(pos_T *lp)
if (lp->col > 0) {
// still within line
lp->col--;
- char_u *p = ml_get(lp->lnum);
+ char *p = ml_get(lp->lnum);
lp->col -= utf_head_off(p, p + lp->col);
return 0;
}
if (lp->lnum > 1) {
// there is a prior line
lp->lnum--;
- char_u *p = ml_get(lp->lnum);
- lp->col = (colnr_T)STRLEN(p);
+ char *p = ml_get(lp->lnum);
+ lp->col = (colnr_T)strlen(p);
lp->col -= utf_head_off(p, p + lp->col);
return 1;
}
diff --git a/src/nvim/memline_defs.h b/src/nvim/memline_defs.h
index 922a2c98d1..552ec1e3a9 100644
--- a/src/nvim/memline_defs.h
+++ b/src/nvim/memline_defs.h
@@ -69,4 +69,4 @@ typedef struct memline {
int ml_usedchunks;
} memline_T;
-#endif // NVIM_MEMLINE_DEFS_H
+#endif // NVIM_MEMLINE_DEFS_H
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index fb36d4ccf4..03cfde6160 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -23,6 +23,7 @@
#include "nvim/message.h"
#include "nvim/sign.h"
#include "nvim/ui.h"
+#include "nvim/ui_compositor.h"
#include "nvim/vim.h"
#ifdef UNIT_TESTING
@@ -60,6 +61,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;
}
@@ -499,22 +502,22 @@ bool striequal(const char *a, const char *b)
return (a == NULL && b == NULL) || (a && b && STRICMP(a, b) == 0);
}
-/*
- * Avoid repeating the error message many times (they take 1 second each).
- * Did_outofmem_msg is reset when a character is read.
- */
+// Avoid repeating the error message many times (they take 1 second each).
+// Did_outofmem_msg is reset when a character is read.
void do_outofmem_msg(size_t size)
{
- if (!did_outofmem_msg) {
- // Don't hide this message
- emsg_silent = 0;
+ if (did_outofmem_msg) {
+ return;
+ }
- /* Must come first to avoid coming back here when printing the error
- * message fails, e.g. when setting v:errmsg. */
- did_outofmem_msg = true;
+ // Don't hide this message
+ emsg_silent = 0;
- semsg(_("E342: Out of memory! (allocating %" PRIu64 " bytes)"), (uint64_t)size);
- }
+ // Must come first to avoid coming back here when printing the error
+ // message fails, e.g. when setting v:errmsg.
+ did_outofmem_msg = true;
+
+ semsg(_("E342: Out of memory! (allocating %" PRIu64 " bytes)"), (uint64_t)size);
}
/// Writes time_t to "buf[8]".
@@ -528,21 +531,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 +559,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 +605,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 +614,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) {
@@ -649,13 +675,11 @@ char *arena_memdupz(Arena *arena, const char *buf, size_t size)
# include "nvim/tag.h"
# include "nvim/window.h"
-/*
- * Free everything that we allocated.
- * Can be used to detect memory leaks, e.g., with ccmalloc.
- * NOTE: This is tricky! Things are freed that functions depend on. Don't be
- * surprised if Vim crashes...
- * Some things can't be freed, esp. things local to a library function.
- */
+// Free everything that we allocated.
+// Can be used to detect memory leaks, e.g., with ccmalloc.
+// NOTE: This is tricky! Things are freed that functions depend on. Don't be
+// surprised if Vim crashes...
+// Some things can't be freed, esp. things local to a library function.
void free_all_mem(void)
{
buf_T *buf, *nextbuf;
@@ -799,6 +823,10 @@ void free_all_mem(void)
nlua_free_all_mem();
ui_free_all_mem();
+ ui_comp_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..d8b7e872d9 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -1,10 +1,8 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * Code for menus. Used for the GUI and 'wildmenu'.
- * GUI/Motif support by Robert Webb
- */
+// Code for menus. Used for the GUI and 'wildmenu'.
+// GUI/Motif support by Robert Webb
#include <assert.h>
#include <inttypes.h>
@@ -141,9 +139,7 @@ void ex_menu(exarg_T *eap)
}
pri_tab[MENUDEPTH] = -1; // mark end of the table
- /*
- * Check for "disable" or "enable" argument.
- */
+ // Check for "disable" or "enable" argument.
if (STRNCMP(arg, "enable", 6) == 0 && ascii_iswhite(arg[6])) {
enable = kTrue;
arg = skipwhite(arg + 6);
@@ -152,9 +148,7 @@ void ex_menu(exarg_T *eap)
arg = skipwhite(arg + 7);
}
- /*
- * If there is no argument, display all menus.
- */
+ // If there is no argument, display all menus.
if (*arg == NUL) {
show_menus(arg, modes);
return;
@@ -168,9 +162,7 @@ void ex_menu(exarg_T *eap)
map_to = menu_translate_tab_and_shift(arg);
- /*
- * If there is only a menu name, display menus with that name.
- */
+ // If there is only a menu name, display menus with that name.
if (*map_to == NUL && !unmenu && enable == kNone) {
show_menus(menu_path, modes);
goto theend;
@@ -185,7 +177,7 @@ void ex_menu(exarg_T *eap)
// Change sensitivity of the menu.
// For the PopUp menu, remove a menu for each mode separately.
// Careful: menu_enable_recurse() changes menu_path.
- if (STRCMP(menu_path, "*") == 0) { // meaning: do all menus
+ if (strcmp(menu_path, "*") == 0) { // meaning: do all menus
menu_path = "";
}
@@ -200,16 +192,12 @@ void ex_menu(exarg_T *eap)
}
menu_enable_recurse(*root_menu_ptr, menu_path, modes, enable);
} else if (unmenu) {
- /*
- * Delete menu(s).
- */
- if (STRCMP(menu_path, "*") == 0) { // meaning: remove all menus
+ // Delete menu(s).
+ if (strcmp(menu_path, "*") == 0) { // meaning: remove all menus
menu_path = "";
}
- /*
- * For the PopUp menu, remove a menu for each mode separately.
- */
+ // For the PopUp menu, remove a menu for each mode separately.
if (menu_is_popup(menu_path)) {
for (i = 0; i < MENU_INDEX_TIP; i++) {
if (modes & (1 << i)) {
@@ -223,10 +211,8 @@ void ex_menu(exarg_T *eap)
// Careful: remove_menu() changes menu_path
remove_menu(root_menu_ptr, menu_path, modes, false);
} else {
- /*
- * Add menu(s).
- * Replace special key codes.
- */
+ // Add menu(s).
+ // Replace special key codes.
if (STRICMP(map_to, "<nop>") == 0) { // "<Nop>" means nothing
map_to = "";
map_buf = NULL;
@@ -242,9 +228,7 @@ void ex_menu(exarg_T *eap)
menuarg.silent[0] = silent;
add_menu_path(menu_path, &menuarg, pri_tab, map_to);
- /*
- * For the PopUp menu, add a menu for each mode separately.
- */
+ // For the PopUp menu, add a menu for each mode separately.
if (menu_is_popup(menu_path)) {
for (i = 0; i < MENU_INDEX_TIP; i++) {
if (modes & (1 << i)) {
@@ -384,11 +368,9 @@ static int add_menu_path(const char *const menu_path, vimmenu_T *menuarg, const
} else {
old_modes = menu->modes;
- /*
- * If this menu option was previously only available in other
- * modes, then make sure it's available for this one now
- * Also enable a menu when it's created or changed.
- */
+ // If this menu option was previously only available in other
+ // modes, then make sure it's available for this one now
+ // Also enable a menu when it's created or changed.
{
menu->modes |= modes;
menu->enabled |= modes;
@@ -405,10 +387,8 @@ static int add_menu_path(const char *const menu_path, vimmenu_T *menuarg, const
}
xfree(path_name);
- /*
- * Only add system menu items which have not been defined yet.
- * First check if this was an ":amenu".
- */
+ // Only add system menu items which have not been defined yet.
+ // First check if this was an ":amenu".
amenu = ((modes & (MENU_NORMAL_MODE | MENU_INSERT_MODE)) ==
(MENU_NORMAL_MODE | MENU_INSERT_MODE));
if (sys_menu) {
@@ -419,7 +399,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);
@@ -491,10 +471,8 @@ erret:
return FAIL;
}
-/*
- * Set the (sub)menu with the given name to enabled or disabled.
- * Called recursively.
- */
+// Set the (sub)menu with the given name to enabled or disabled.
+// Called recursively.
static int menu_enable_recurse(vimmenu_T *menu, char *name, int modes, int enable)
{
char *p;
@@ -522,11 +500,9 @@ static int menu_enable_recurse(vimmenu_T *menu, char *name, int modes, int enabl
menu->enabled &= ~modes;
}
- /*
- * When name is empty, we are doing all menu items for the given
- * modes, so keep looping, otherwise we are just doing the named
- * menu item (which has been found) so break here.
- */
+ // When name is empty, we are doing all menu items for the given
+ // modes, so keep looping, otherwise we are just doing the named
+ // menu item (which has been found) so break here.
if (*name != NUL && *name != '*') {
break;
}
@@ -577,11 +553,9 @@ static int remove_menu(vimmenu_T **menup, char *name, int modes, bool silent)
return FAIL;
}
- /*
- * When name is empty, we are removing all menu items for the given
- * modes, so keep looping, otherwise we are just removing the named
- * menu item (which has been found) so break here.
- */
+ // When name is empty, we are removing all menu items for the given
+ // modes, so keep looping, otherwise we are just removing the named
+ // menu item (which has been found) so break here.
if (*name != NUL) {
break;
}
@@ -628,9 +602,7 @@ static int remove_menu(vimmenu_T **menup, char *name, int modes, bool silent)
return OK;
}
-/*
- * Free the given menu structure and remove it from the linked list.
- */
+// Free the given menu structure and remove it from the linked list.
static void free_menu(vimmenu_T **menup)
{
int i;
@@ -652,9 +624,7 @@ static void free_menu(vimmenu_T **menup)
xfree(menu);
}
-/*
- * Free the menu->string with the given index.
- */
+// Free the menu->string with the given index.
static void free_menu_string(vimmenu_T *menu, int idx)
{
int count = 0;
@@ -853,7 +823,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) {
@@ -888,7 +858,7 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth)
if (*menu->strings[bit] == NUL) {
msg_puts_attr("<Nop>", HL_ATTR(HLF_8));
} else {
- msg_outtrans_special((char_u *)menu->strings[bit], false, 0);
+ msg_outtrans_special(menu->strings[bit], false, 0);
}
}
}
@@ -909,16 +879,12 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth)
}
}
-/*
- * Used when expanding menu names.
- */
+// Used when expanding menu names.
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.
- */
+// Work out what to complete when doing command line completion of menu names.
char *set_context_in_menu_cmd(expand_T *xp, const char *cmd, char *arg, bool forceit)
FUNC_ATTR_NONNULL_ALL
{
@@ -933,7 +899,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 +923,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 == '.') {
@@ -994,10 +960,8 @@ char *set_context_in_menu_cmd(expand_T *xp, const char *cmd, char *arg, bool for
// Found menu
if ((*p != NUL && menu->children == NULL)
|| ((menu->modes & expand_modes) == 0x0)) {
- /*
- * Menu path continues, but we have reached a leaf.
- * Or menu exists only in another mode.
- */
+ // Menu path continues, but we have reached a leaf.
+ // Or menu exists only in another mode.
xfree(path_name);
return NULL;
}
@@ -1024,10 +988,8 @@ char *set_context_in_menu_cmd(expand_T *xp, const char *cmd, char *arg, bool for
return NULL;
}
-/*
- * Function given to ExpandGeneric() to obtain the list of (sub)menus (not
- * entries).
- */
+// Function given to ExpandGeneric() to obtain the list of (sub)menus (not
+// entries).
char *get_menu_name(expand_T *xp, int idx)
{
static vimmenu_T *menu = NULL;
@@ -1056,7 +1018,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 {
@@ -1073,10 +1035,8 @@ char *get_menu_name(expand_T *xp, int idx)
return str;
}
-/*
- * Function given to ExpandGeneric() to obtain the list of menus and menu
- * entries.
- */
+// Function given to ExpandGeneric() to obtain the list of menus and menu
+// entries.
char *get_menu_names(expand_T *xp, int idx)
{
static vimmenu_T *menu = NULL;
@@ -1163,10 +1123,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 +1139,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;
}
@@ -1314,10 +1272,8 @@ static char *get_menu_mode_str(int modes)
return "";
}
-/*
- * Modify a menu name starting with "PopUp" to include the mode character.
- * Returns the name in allocated memory.
- */
+// Modify a menu name starting with "PopUp" to include the mode character.
+// Returns the name in allocated memory.
static char *popup_mode_name(char *name, int idx)
{
size_t len = STRLEN(name);
@@ -1405,10 +1361,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] == '-';
@@ -1734,9 +1688,7 @@ theend:
return menu;
}
-/*
- * Translation of menu names. Just a simple lookup table.
- */
+// Translation of menu names. Just a simple lookup table.
typedef struct {
char *from; // English name
@@ -1752,11 +1704,9 @@ static garray_T menutrans_ga = GA_EMPTY_INIT_VALUE;
xfree(_mt->from_noamp); \
xfree(_mt->to)
-/*
- * ":menutrans".
- * This function is also defined without the +multi_lang feature, in which
- * case the commands are ignored.
- */
+// ":menutrans".
+// This function is also defined without the +multi_lang feature, in which
+// case the commands are ignored.
void ex_menutranslate(exarg_T *eap)
{
char *arg = eap->arg;
@@ -1766,9 +1716,7 @@ void ex_menutranslate(exarg_T *eap)
ga_init(&menutrans_ga, (int)sizeof(menutrans_T), 5);
}
- /*
- * ":menutrans clear": clear all translations.
- */
+ // ":menutrans clear": clear all translations.
if (STRNCMP(arg, "clear", 5) == 0 && ends_excmd(*skipwhite(arg + 5))) {
GA_DEEP_CLEAR(&menutrans_ga, menutrans_T, FREE_MENUTRANS);
@@ -1800,9 +1748,7 @@ void ex_menutranslate(exarg_T *eap)
}
}
-/*
- * Find the character just after one part of a menu name.
- */
+// Find the character just after one part of a menu name.
static char *menu_skip_part(char *p)
{
while (*p != NUL && *p != '.' && !ascii_iswhite(*p)) {
@@ -1814,10 +1760,8 @@ static char *menu_skip_part(char *p)
return p;
}
-/*
- * Lookup part of a menu name in the translations.
- * Return a pointer to the translation or NULL if not found.
- */
+// Lookup part of a menu name in the translations.
+// Return a pointer to the translation or NULL if not found.
static char *menutrans_lookup(char *name, int len)
{
menutrans_T *tp = (menutrans_T *)menutrans_ga.ga_data;
@@ -1845,9 +1789,7 @@ static char *menutrans_lookup(char *name, int len)
return NULL;
}
-/*
- * Unescape the name in the translate dictionary table.
- */
+// Unescape the name in the translate dictionary table.
static void menu_unescape_name(char *name)
{
char *p;
@@ -1859,10 +1801,8 @@ static void menu_unescape_name(char *name)
}
}
-/*
- * Isolate the menu name.
- * Skip the menu name, and translate <Tab> into a real TAB.
- */
+// Isolate the menu name.
+// Skip the menu name, and translate <Tab> into a real TAB.
static char *menu_translate_tab_and_shift(char *arg_start)
{
char *arg = arg_start;
@@ -1945,7 +1885,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..2d23797bc8 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1,9 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * message.c: functions for displaying messages on the command line
- */
+// message.c: functions for displaying messages on the command line
#include <assert.h>
#include <inttypes.h>
@@ -48,75 +46,71 @@
#include "nvim/ui_compositor.h"
#include "nvim/vim.h"
-/*
- * To be able to scroll back at the "more" and "hit-enter" prompts we need to
- * store the displayed text and remember where screen lines start.
- */
+// To be able to scroll back at the "more" and "hit-enter" prompts we need to
+// store the displayed text and remember where screen lines start.
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
+ char sb_text[1]; // text to be displayed, actually longer
};
// Magic chars used in confirm dialog strings
#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
-static char_u *confirm_msg = NULL; // ":confirm" message
-static char_u *confirm_msg_tail; // tail of confirm_msg
+static char *confirm_msg = NULL; // ":confirm" message
+static char *confirm_msg_tail; // tail of confirm_msg
MessageHistoryEntry *first_msg_hist = NULL;
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()
-/*
- * When writing messages to the screen, there are many different situations.
- * A number of variables is used to remember the current state:
- * msg_didany true when messages were written since the last time the
- * user reacted to a prompt.
- * Reset: After hitting a key for the hit-return prompt,
- * hitting <CR> for the command line or input().
- * Set: When any message is written to the screen.
- * msg_didout true when something was written to the current line.
- * Reset: When advancing to the next line, when the current
- * text can be overwritten.
- * Set: When any message is written to the screen.
- * msg_nowait No extra delay for the last drawn message.
- * Used in normal_cmd() before the mode message is drawn.
- * emsg_on_display There was an error message recently. Indicates that there
- * should be a delay before redrawing.
- * msg_scroll The next message should not overwrite the current one.
- * 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()
- * 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.
- * lines_left Number of lines available for messages before the
- * more-prompt is to be given. -1 when not set.
- * need_wait_return true when the hit-return prompt is needed.
- * Reset: After giving the hit-return prompt, when the user
- * has answered some other prompt.
- * Set: When the ruler or typeahead display is overwritten,
- * scrolling the screen for some message.
- * keep_msg Message to be displayed after redrawing the screen, in
- * main_loop().
- * This is an allocated string or NULL when not used.
- */
+// When writing messages to the screen, there are many different situations.
+// A number of variables is used to remember the current state:
+// msg_didany true when messages were written since the last time the
+// user reacted to a prompt.
+// Reset: After hitting a key for the hit-return prompt,
+// hitting <CR> for the command line or input().
+// Set: When any message is written to the screen.
+// msg_didout true when something was written to the current line.
+// Reset: When advancing to the next line, when the current
+// text can be overwritten.
+// Set: When any message is written to the screen.
+// msg_nowait No extra delay for the last drawn message.
+// Used in normal_cmd() before the mode message is drawn.
+// emsg_on_display There was an error message recently. Indicates that there
+// should be a delay before redrawing.
+// msg_scroll The next message should not overwrite the current one.
+// 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()
+// 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.
+// lines_left Number of lines available for messages before the
+// more-prompt is to be given. -1 when not set.
+// need_wait_return true when the hit-return prompt is needed.
+// Reset: After giving the hit-return prompt, when the user
+// has answered some other prompt.
+// Set: When the ruler or typeahead display is overwritten,
+// scrolling the screen for some message.
+// keep_msg Message to be displayed after redrawing the screen, in
+// main_loop().
+// This is an allocated string or NULL when not used.
// Extended msg state, currently used for external UIs with ext_messages
static const char *msg_ext_kind = NULL;
@@ -215,7 +209,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);
@@ -251,7 +245,7 @@ void msg_multiline_attr(const char *s, int attr, bool check_int, bool *need_clea
if (next_spec != NULL) {
// Printing all char that are before the char found by strpbrk
- msg_outtrans_len_attr((const char_u *)s, (int)(next_spec - s), attr);
+ msg_outtrans_len_attr(s, (int)(next_spec - s), attr);
if (*next_spec != TAB && *need_clear) {
msg_clr_eos();
@@ -265,7 +259,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);
}
}
@@ -294,7 +288,7 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
{
static int entered = 0;
int retval;
- char_u *buf = NULL;
+ char *buf = NULL;
if (keep && multiline) {
// Not implemented. 'multiline' is only used by nvim-added messages,
@@ -305,7 +299,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;
}
@@ -313,38 +307,36 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
set_vim_var_string(VV_STATUSMSG, s, -1);
}
- /*
- * It is possible that displaying a messages causes a problem (e.g.,
- * when redrawing the window), which causes another message, etc.. To
- * break this loop, limit the recursiveness to 3 levels.
- */
+ // It is possible that displaying a messages causes a problem (e.g.,
+ // when redrawing the window), which causes another message, etc.. To
+ // 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
- && STRCMP(s, last_msg_hist->msg))) {
+ && strcmp(s, last_msg_hist->msg))) {
add_msg_hist(s, -1, attr, multiline);
}
// Truncate the message if needed.
msg_start();
- buf = msg_strtrunc((char_u *)s, FALSE);
+ buf = msg_strtrunc((char *)s, false);
if (buf != NULL) {
- s = (const char *)buf;
+ s = buf;
}
bool need_clear = true;
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();
@@ -367,9 +359,9 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
/// @return an allocated string or NULL when no truncating is done.
///
/// @param force always truncate
-char_u *msg_strtrunc(char_u *s, int force)
+char *msg_strtrunc(char *s, int force)
{
- char_u *buf = NULL;
+ char *buf = NULL;
int len;
int room;
@@ -377,7 +369,7 @@ char_u *msg_strtrunc(char_u *s, int force)
if ((!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL)
&& !exmode_active && msg_silent == 0 && !ui_has(kUIMessages))
|| force) {
- len = vim_strsize((char *)s);
+ len = vim_strsize(s);
if (msg_scrolled != 0) {
// Use all the columns.
room = (Rows - msg_row) * Columns - 1;
@@ -390,7 +382,7 @@ char_u *msg_strtrunc(char_u *s, int force)
// composing chars)
len = (room + 2) * 18;
buf = xmalloc((size_t)len);
- trunc_string((char *)s, (char *)buf, room, len);
+ trunc_string(s, buf, room, len);
}
}
return buf;
@@ -420,7 +412,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;
@@ -444,7 +436,7 @@ void trunc_string(char *s, char *buf, int room_in, int buflen)
half = i = (int)STRLEN(s);
for (;;) {
do {
- half = half - utf_head_off((char_u *)s, (char_u *)s + half - 1) - 1;
+ half = half - utf_head_off(s, s + half - 1) - 1;
} while (half > 0 && utf_iscomposing(utf_ptr2char(s + half)));
n = ptr2cells(s + half);
if (len + n > room || half == 0) {
@@ -483,10 +475,8 @@ void trunc_string(char *s, char *buf, int room_in, int buflen)
}
}
-/*
- * Note: Caller of smsg() and smsg_attr() must check the resulting string is
- * shorter than IOSIZE!!!
- */
+// Note: Caller of smsg() and smsg_attr() must check the resulting string is
+// shorter than IOSIZE!!!
int smsg(const char *s, ...)
FUNC_ATTR_PRINTF(1, 2)
@@ -522,10 +512,8 @@ int smsg_attr_keep(int attr, const char *s, ...)
return msg_attr_keep((const char *)IObuff, attr, true, false);
}
-/*
- * Remember the last sourcing name/lnum used in an error message, so that it
- * isn't printed each time when it didn't change.
- */
+// Remember the last sourcing name/lnum used in an error message, so that it
+// isn't printed each time when it didn't change.
static int last_sourcing_lnum = 0;
static char *last_sourcing_name = NULL;
@@ -634,18 +622,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 +653,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
@@ -681,10 +669,8 @@ static bool emsg_multiline(const char *s, bool multiline)
// set "v:errmsg", also when using ":silent! cmd"
set_vim_var_string(VV_ERRMSG, s, -1);
- /*
- * When using ":silent! cmd" ignore error messages.
- * But do write it to the redirection file.
- */
+ // When using ":silent! cmd" ignore error messages.
+ // But do write it to the redirection file.
if (emsg_silent != 0) {
if (!emsg_noredir) {
msg_start();
@@ -745,7 +731,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 +752,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);
@@ -900,7 +886,7 @@ char *msg_trunc_attr(char *s, bool force, int attr)
// Add message to history before truncating.
add_msg_hist(s, -1, attr, false);
- char *ts = (char *)msg_may_trunc(force, (char_u *)s);
+ char *ts = msg_may_trunc(force, s);
msg_hist_off = true;
n = msg_attr(ts, attr);
@@ -917,14 +903,14 @@ char *msg_trunc_attr(char *s, bool force, int attr)
/// @return a pointer to where the truncated message starts.
///
/// @note: May change the message by replacing a character with '<'.
-char_u *msg_may_trunc(bool force, char_u *s)
+char *msg_may_trunc(bool force, char *s)
{
int room;
room = (Rows - cmdline_row - 1) * Columns + sc_col - 1;
if ((force || (shortmess(SHM_TRUNC) && !exmode_active))
&& (int)STRLEN(s) - room > 0 && p_ch > 0) {
- int size = vim_strsize((char *)s);
+ int size = vim_strsize(s);
// There may be room anyway when there are multibyte chars.
if (size <= room) {
@@ -932,8 +918,8 @@ char_u *msg_may_trunc(bool force, char_u *s)
}
int n;
for (n = 0; size >= room;) {
- size -= utf_ptr2cells((char *)s + n);
- n += utfc_ptr2len((char *)s + n);
+ size -= utf_ptr2cells(s + n);
+ n += utfc_ptr2len(s + n);
}
n--;
s += n;
@@ -992,7 +978,7 @@ static void add_msg_hist_multiattr(const char *s, int len, int attr, bool multil
while (len > 0 && s[len - 1] == '\n') {
len--;
}
- p->msg = (char_u *)xmemdupz(s, (size_t)len);
+ p->msg = xmemdupz(s, (size_t)len);
} else {
p->msg = NULL;
}
@@ -1042,7 +1028,7 @@ void ex_messages(void *const eap_p)
struct msg_hist *p;
int c = 0;
- if (STRCMP(eap->arg, "clear") == 0) {
+ if (strcmp(eap->arg, "clear") == 0) {
int keep = eap->addr_count == 0 ? 0 : eap->line2;
while (msg_hist_len > keep) {
@@ -1086,7 +1072,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]) {
@@ -1109,7 +1095,7 @@ void ex_messages(void *const eap_p)
if (kv_size(p->multiattr)) {
msg_multiattr(p->multiattr, p->kind, false);
} else if (p->msg != NULL) {
- msg_attr_keep((char *)p->msg, p->attr, false, p->multiline);
+ msg_attr_keep(p->msg, p->attr, false, p->multiline);
}
}
msg_hist_off = false;
@@ -1131,7 +1117,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 +1129,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
@@ -1156,12 +1142,10 @@ void wait_return(int redraw)
return;
}
- /*
- * When inside vgetc(), we can't wait for a typed character at all.
- * With the global command (and some others) we only need one return at
- * the end. Adjust cmdline_row to avoid the next message overwriting the
- * last one.
- */
+ // When inside vgetc(), we can't wait for a typed character at all.
+ // With the global command (and some others) we only need one return at
+ // the end. Adjust cmdline_row to avoid the next message overwriting the
+ // last one.
if (vgetc_busy > 0) {
return;
}
@@ -1177,12 +1161,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.
@@ -1226,12 +1210,10 @@ void wait_return(int redraw)
reg_recording = save_reg_recording;
scriptout = save_scriptout;
- /*
- * Allow scrolling back in the messages.
- * Also accept scroll-down commands when messages fill the screen,
- * to avoid that typing one 'j' too many makes the messages
- * disappear.
- */
+ // Allow scrolling back in the messages.
+ // Also accept scroll-down commands when messages fill the screen,
+ // to avoid that typing one 'j' too many makes the messages
+ // disappear.
if (p_more) {
if (c == 'b' || c == 'k' || c == 'u' || c == 'g'
|| c == K_UP || c == K_PAGEUP) {
@@ -1247,8 +1229,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();
@@ -1268,9 +1250,7 @@ void wait_return(int redraw)
|| c == K_MOUSEDOWN || c == K_MOUSEUP
|| c == K_MOUSEMOVE);
os_breakcheck();
- /*
- * Avoid that the mouse-up event causes visual mode to start.
- */
+ // Avoid that the mouse-up event causes visual mode to start.
if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE
|| c == K_X1MOUSE || c == K_X2MOUSE) {
(void)jump_to_mouse(MOUSE_SETPOS, NULL, 0);
@@ -1307,7 +1287,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 +1296,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 +1330,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;
}
@@ -1497,20 +1477,20 @@ void msg_outnum(long n)
msg_puts(buf);
}
-void msg_home_replace(char_u *fname)
+void msg_home_replace(char *fname)
{
msg_home_replace_attr(fname, 0);
}
-void msg_home_replace_hl(char_u *fname)
+void msg_home_replace_hl(char *fname)
{
msg_home_replace_attr(fname, HL_ATTR(HLF_D));
}
-static void msg_home_replace_attr(char_u *fname, int attr)
+static void msg_home_replace_attr(char *fname, int attr)
{
- char *name = home_replace_save(NULL, (char *)fname);
- msg_outtrans_attr((char_u *)name, attr);
+ char *name = home_replace_save(NULL, fname);
+ msg_outtrans_attr(name, attr);
xfree(name);
}
@@ -1521,15 +1501,15 @@ 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);
}
-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);
}
@@ -1538,11 +1518,11 @@ int msg_outtrans_len(const char_u *str, int len)
/// 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) {
+ if ((l = utfc_ptr2len(p)) > 1) {
msg_outtrans_len_attr(p, l, attr);
return p + l;
}
@@ -1550,12 +1530,12 @@ char_u *msg_outtrans_one(char_u *p, int attr)
return p + 1;
}
-int msg_outtrans_len_attr(const char_u *msgstr, int len, int attr)
+int msg_outtrans_len_attr(const char *msgstr, int len, int attr)
{
int retval = 0;
- const char *str = (const char *)msgstr;
- const char *plain_start = (const char *)msgstr;
- char_u *s;
+ const char *str = msgstr;
+ const char *plain_start = msgstr;
+ char *s;
int mb_l;
int c;
int save_got_int = got_int;
@@ -1575,13 +1555,11 @@ int msg_outtrans_len_attr(const char_u *msgstr, int len, int attr)
msg_puts_attr(" ", attr);
}
- /*
- * Go over the string. Special characters are translated and printed.
- * Normal characters are printed several at a time.
- */
+ // Go over the string. Special characters are translated and printed.
+ // Normal characters are printed several at a time.
while (--len >= 0 && !got_int) {
// Don't include composing chars after the end.
- mb_l = utfc_ptr2len_len((char_u *)str, len + 1);
+ mb_l = utfc_ptr2len_len(str, len + 1);
if (mb_l > 1) {
c = utf_ptr2char(str);
if (vim_isprintc(c)) {
@@ -1601,7 +1579,7 @@ int msg_outtrans_len_attr(const char_u *msgstr, int len, int attr)
len -= mb_l - 1;
str += mb_l;
} else {
- s = transchar_byte((uint8_t)(*str));
+ s = (char *)transchar_byte((uint8_t)(*str));
if (s[1] != NUL) {
// Unprintable char: print the printable chars so far and the
// translation of the unprintable char.
@@ -1628,12 +1606,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 +1620,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 +1632,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.
@@ -1662,12 +1641,12 @@ void msg_make(char_u *arg)
///
/// @param from true for LHS of a mapping
/// @param maxlen screen columns, 0 for unlimited
-int msg_outtrans_special(const char_u *strstart, bool from, int maxlen)
+int msg_outtrans_special(const char *strstart, bool from, int maxlen)
{
if (strstart == NULL) {
return 0; // Do nothing.
}
- const char_u *str = strstart;
+ const char *str = strstart;
int retval = 0;
int attr = HL_ATTR(HLF_8);
@@ -1678,7 +1657,7 @@ int msg_outtrans_special(const char_u *strstart, bool from, int maxlen)
text = "<Space>";
str++;
} else {
- text = str2special((const char **)&str, from, false);
+ text = str2special(&str, from, false);
}
if (text[0] != NUL && text[1] == NUL) {
// single-byte character or illegal byte
@@ -1817,20 +1796,20 @@ void str2specialbuf(const char *sp, char *buf, size_t len)
}
/// print line for :print or :list command
-void msg_prt_line(char_u *s, int list)
+void msg_prt_line(char *s, int list)
{
int c;
int col = 0;
int n_extra = 0;
int c_extra = 0;
int c_final = 0;
- char_u *p_extra = NULL; // init to make SASC shut up
+ char *p_extra = NULL; // init to make SASC shut up
int n;
int attr = 0;
- char_u *lead = NULL;
+ char *lead = NULL;
bool in_multispace = false;
int multispace_pos = 0;
- char_u *trail = NULL;
+ char *trail = NULL;
int l;
if (curwin->w_p_list) {
@@ -1872,16 +1851,16 @@ void msg_prt_line(char_u *s, int list)
c = c_extra;
} else {
assert(p_extra != NULL);
- c = *p_extra++;
+ c = (unsigned char)(*p_extra++);
}
- } else if ((l = utfc_ptr2len((char *)s)) > 1) {
- col += utf_ptr2cells((char *)s);
+ } else if ((l = utfc_ptr2len(s)) > 1) {
+ col += utf_ptr2cells(s);
char buf[MB_MAXBYTES + 1];
if (l >= MB_MAXBYTES) {
xstrlcpy(buf, "?", sizeof(buf));
} else if (curwin->w_p_lcs_chars.nbsp != NUL && list
- && (utf_ptr2char((char *)s) == 160
- || utf_ptr2char((char *)s) == 0x202f)) {
+ && (utf_ptr2char(s) == 160
+ || utf_ptr2char(s) == 0x202f)) {
int len = utf_char2bytes(curwin->w_p_lcs_chars.nbsp, buf);
buf[len] = NUL;
} else {
@@ -1893,7 +1872,7 @@ void msg_prt_line(char_u *s, int list)
continue;
} else {
attr = 0;
- c = *s++;
+ c = (unsigned char)(*s++);
in_multispace = c == ' ' && ((col > 0 && s[-2] == ' ') || *s == ' ');
if (!in_multispace) {
multispace_pos = 0;
@@ -1919,7 +1898,7 @@ void msg_prt_line(char_u *s, int list)
c = curwin->w_p_lcs_chars.nbsp;
attr = HL_ATTR(HLF_0);
} else if (c == NUL && list && curwin->w_p_lcs_chars.eol != NUL) {
- p_extra = (char_u *)"";
+ p_extra = "";
c_extra = NUL;
c_final = NUL;
n_extra = 1;
@@ -1928,10 +1907,10 @@ void msg_prt_line(char_u *s, int list)
s--;
} else if (c != NUL && (n = byte2cells(c)) > 1) {
n_extra = n - 1;
- p_extra = transchar_byte(c);
+ p_extra = (char *)transchar_byte(c);
c_extra = NUL;
c_final = NUL;
- c = *p_extra++;
+ c = (unsigned char)(*p_extra++);
// Use special coloring to be able to distinguish <hex> from
// the same in plain text.
attr = HL_ATTR(HLF_0);
@@ -1976,13 +1955,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.
@@ -2022,12 +2001,12 @@ void msg_puts_title(const char *s)
/// Show a message in such a way that it always fits in the line. Cut out a
/// part in the middle and replace it with "..." when necessary.
/// Does not handle multi-byte characters!
-void msg_outtrans_long_attr(char_u *longstr, int attr)
+void msg_outtrans_long_attr(char *longstr, int attr)
{
msg_outtrans_long_len_attr(longstr, (int)STRLEN(longstr), attr);
}
-void msg_outtrans_long_len_attr(char_u *longstr, int len, int attr)
+void msg_outtrans_long_len_attr(char *longstr, int len, int attr)
{
int slen = len;
int room;
@@ -2104,7 +2083,7 @@ void msg_puts_attr_len(const char *const str, const ptrdiff_t len, int attr)
}
}
if (!msg_use_printf() || (headless_mode && default_grid.chars)) {
- msg_puts_display((const char_u *)str, (int)len, attr, false);
+ msg_puts_display(str, (int)len, attr, false);
}
need_fileinfo = false;
@@ -2147,10 +2126,10 @@ static void msg_ext_emit_chunk(void)
/// The display part of msg_puts_attr_len().
/// May be called recursively to display scroll-back text.
-static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurse)
+static void msg_puts_display(const char *str, int maxlen, int attr, int recurse)
{
- const char_u *s = str;
- const char_u *t_s = str; // String from "t_s" to "s" is still todo.
+ const char *s = str;
+ const char *t_s = str; // String from "t_s" to "s" is still todo.
int t_col = 0; // Screen cells todo, 0 when "t_s" not used.
int l;
int cw;
@@ -2185,12 +2164,12 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
&& (*s == '\n' || (cmdmsg_rl
? (msg_col <= 1
|| (*s == TAB && msg_col <= 7)
- || (utf_ptr2cells((char *)s) > 1
+ || (utf_ptr2cells(s) > 1
&& msg_col <= 2))
: ((*s != '\r' && msg_col + t_col >= Columns - 1)
|| (*s == TAB
&& msg_col + t_col >= ((Columns - 1) & ~7))
- || (utf_ptr2cells((char *)s) > 1
+ || (utf_ptr2cells(s) > 1
&& msg_col + t_col >= Columns - 2))))) {
// The screen is scrolled up when at the last row (some terminals
// scroll automatically, some don't. To avoid problems we scroll
@@ -2206,7 +2185,7 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
}
// Scroll the screen up one line.
- bool has_last_char = (*s >= ' ' && !cmdmsg_rl);
+ bool has_last_char = ((uint8_t)(*s) >= ' ' && !cmdmsg_rl);
msg_scroll_up(!has_last_char);
msg_row = Rows - 2;
@@ -2220,9 +2199,9 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
// Avoid including composing chars after the end.
l = utfc_ptr2len_len(s, (int)((str + maxlen) - s));
} else {
- l = utfc_ptr2len((char *)s);
+ l = utfc_ptr2len(s);
}
- s = screen_puts_mbyte((char_u *)s, l, attr);
+ s = screen_puts_mbyte((char *)s, l, attr);
did_last_char = true;
} else {
did_last_char = false;
@@ -2243,16 +2222,14 @@ 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--;
}
- /*
- * If screen is completely filled and 'more' is set then wait
- * for a character.
- */
+ // If screen is completely filled and 'more' is set then wait
+ // for a character.
if (lines_left > 0) {
lines_left--;
}
@@ -2275,7 +2252,7 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
wrap = *s == '\n'
|| msg_col + t_col >= Columns
- || (utf_ptr2cells((char *)s) > 1
+ || (utf_ptr2cells(s) > 1
&& msg_col + t_col >= Columns - 1)
;
if (t_col > 0 && (wrap || *s == '\r' || *s == '\b'
@@ -2311,20 +2288,20 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
} while (msg_col & 7);
} else if (*s == BELL) { // beep (from ":sh")
vim_beep(BO_SH);
- } else if (*s >= 0x20) { // printable char
- cw = utf_ptr2cells((char *)s);
+ } else if ((uint8_t)(*s) >= 0x20) { // printable char
+ cw = utf_ptr2cells(s);
if (maxlen >= 0) {
// avoid including composing chars after the end
l = utfc_ptr2len_len(s, (int)((str + maxlen) - s));
} else {
- l = utfc_ptr2len((char *)s);
+ l = utfc_ptr2len(s);
}
// When drawing from right to left or when a double-wide character
// doesn't fit, draw a single character here. Otherwise collect
// 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 = screen_puts_mbyte((char *)s, l, attr) - 1;
} else {
msg_screen_putchar(*s, attr);
}
@@ -2353,13 +2330,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;
}
@@ -2373,7 +2350,7 @@ bool msg_use_msgsep(void)
{
// the full-screen scroll behavior doesn't really make sense with
// 'ext_multigrid'
- return ((dy_flags & DY_MSGSEP) || ui_has(kUIMultigrid));
+ return (dy_flags & DY_MSGSEP) || ui_has(kUIMultigrid);
}
bool msg_do_throttle(void)
@@ -2478,7 +2455,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 +2483,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 +2534,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 +2591,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 +2626,7 @@ void show_sb_text(void)
vim_beep(BO_MESS);
} else {
do_more_prompt('G');
- wait_return(FALSE);
+ wait_return(false);
}
}
@@ -2668,7 +2645,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;
}
}
@@ -2678,7 +2655,7 @@ void msg_sb_eol(void)
static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp)
{
msgchunk_T *mp = smp;
- char_u *p;
+ char *p;
for (;;) {
msg_row = row;
@@ -2687,7 +2664,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 +2675,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 +2694,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 +2762,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 +2793,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,12 +2801,10 @@ static int do_more_prompt(int typed_char)
State = MODE_ASKMORE;
setmouse();
if (typed_char == NUL) {
- msg_moremsg(FALSE);
+ msg_moremsg(false);
}
for (;;) {
- /*
- * Get a typed character directly from the user.
- */
+ // Get a typed character directly from the user.
if (used_typed_char != NUL) {
c = used_typed_char; // was typed at hit-enter prompt
used_typed_char = NUL;
@@ -2898,10 +2872,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 +2891,7 @@ static int do_more_prompt(int typed_char)
break;
default: // no valid response
- msg_moremsg(TRUE);
+ msg_moremsg(true);
continue;
}
@@ -2936,8 +2910,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);
}
@@ -3081,14 +3054,13 @@ static void msg_screen_putchar(int c, int attr)
void msg_moremsg(int full)
{
int attr;
- char_u *s = (char_u *)_("-- More --");
+ char *s = _("-- More --");
attr = hl_combine_attr(HL_ATTR(HLF_MSG), HL_ATTR(HLF_M));
grid_puts(&msg_grid_adj, 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 "),
- Rows - 1, vim_strsize((char *)s), attr);
+ grid_puts(&msg_grid_adj, _(" SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "),
+ Rows - 1, vim_strsize(s), attr);
}
}
@@ -3167,17 +3139,15 @@ 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)
{
- /*
- * If the string is larger than the window,
- * or the ruler option is set and we run into it,
- * we have to redraw the window.
- * Do not do this if we are abandoning the file or editing the command line.
- */
+ // If the string is larger than the window,
+ // or the ruler option is set and we run into it,
+ // we have to redraw the window.
+ // Do not do this if we are abandoning the file or editing the command line.
if (!exiting && need_wait_return && !(State & MODE_CMDLINE)) {
wait_return(false);
return false;
@@ -3245,8 +3215,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;
}
}
}
@@ -3283,7 +3253,7 @@ void msg_check(void)
/// @param maxlen if -1, write the whole string, otherwise up to "maxlen" bytes.
static void redir_write(const char *const str, const ptrdiff_t maxlen)
{
- const char_u *s = (char_u *)str;
+ const char *s = str;
static int cur_col = 0;
if (maxlen == 0) {
@@ -3308,7 +3278,7 @@ static void redir_write(const char *const str, const ptrdiff_t maxlen)
ga_concat_len(capture_ga, " ", 1);
}
if (redir_reg) {
- write_reg_contents(redir_reg, (char_u *)" ", 1, true);
+ write_reg_contents(redir_reg, " ", 1, true);
} else if (redir_vname) {
var_redir_str(" ", -1);
} else if (redir_fd != NULL) {
@@ -3334,7 +3304,7 @@ static void redir_write(const char *const str, const ptrdiff_t maxlen)
// Write and adjust the current column.
while (*s != NUL
- && (maxlen < 0 || (int)(s - (const char_u *)str) < maxlen)) {
+ && (maxlen < 0 || (int)(s - str) < maxlen)) {
if (!redir_reg && !redir_vname && !capture_ga) {
if (redir_fd != NULL) {
putc(*s, redir_fd);
@@ -3392,7 +3362,7 @@ void verbose_enter_scroll(void)
msg_silent++;
} else {
// always scroll up, don't overwrite
- msg_scroll = TRUE;
+ msg_scroll = true;
}
}
@@ -3415,7 +3385,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 +3395,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;
@@ -3471,9 +3441,9 @@ void give_warning(char *message, bool hl)
no_wait_return--;
}
-void give_warning2(char_u *const message, char_u *const a1, bool hl)
+void give_warning2(char *const message, char *const a1, bool hl)
{
- vim_snprintf((char *)IObuff, IOSIZE, (char *)message, a1);
+ vim_snprintf((char *)IObuff, IOSIZE, message, a1);
give_warning((char *)IObuff, hl);
}
@@ -3524,13 +3494,13 @@ 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)
+int do_dialog(int type, char *title, char *message, char *buttons, int dfltbutton, char *textfield,
+ int ex_cmd)
{
int retval = 0;
- char_u *hotkeys;
+ char *hotkeys;
int c;
int i;
@@ -3547,10 +3517,8 @@ int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfl
State = MODE_CONFIRM;
setmouse();
- /*
- * Since we wait for a keypress, don't make the
- * user press RETURN as well afterwards.
- */
+ // Since we wait for a keypress, don't make the
+ // user press RETURN as well afterwards.
no_wait_return++;
hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
@@ -3580,10 +3548,10 @@ int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfl
c = mb_tolower(c);
retval = 1;
for (i = 0; hotkeys[i]; i++) {
- if (utf_ptr2char((char *)hotkeys + i) == c) {
+ if (utf_ptr2char(hotkeys + i) == c) {
break;
}
- i += utfc_ptr2len((char *)hotkeys + i) - 1;
+ i += utfc_ptr2len(hotkeys + i) - 1;
retval++;
}
if (hotkeys[i]) {
@@ -3610,14 +3578,14 @@ int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfl
/// characters. Return the length of the character in bytes.
///
/// @param lowercase make character lower case
-static int copy_char(const char_u *from, char_u *to, bool lowercase)
+static int copy_char(const char *from, char *to, bool lowercase)
FUNC_ATTR_NONNULL_ALL
{
if (lowercase) {
- int c = mb_tolower(utf_ptr2char((char *)from));
- return utf_char2bytes(c, (char *)to);
+ int c = mb_tolower(utf_ptr2char(from));
+ return utf_char2bytes(c, to);
}
- int len = utfc_ptr2len((char *)from);
+ int len = utfc_ptr2len(from);
memmove(to, from, (size_t)len);
return len;
}
@@ -3637,7 +3605,7 @@ static int copy_char(const char_u *from, char_u *to, bool lowercase)
/// corresponding button has a hotkey
///
/// @return Pointer to memory allocated for storing hotkeys
-static char_u *console_dialog_alloc(const char_u *message, char_u *buttons, bool has_hotkey[])
+static char *console_dialog_alloc(const char *message, char *buttons, bool has_hotkey[])
{
int lenhotkey = HOTK_LEN; // count first button
has_hotkey[0] = false;
@@ -3645,7 +3613,7 @@ static char_u *console_dialog_alloc(const char_u *message, char_u *buttons, bool
// Compute the size of memory to allocate.
int len = 0;
int idx = 0;
- char_u *r = buttons;
+ char *r = buttons;
while (*r) {
if (*r == DLG_BUTTON_SEP) {
len += 3; // '\n' -> ', '; 'x' -> '(x)'
@@ -3691,11 +3659,11 @@ static char_u *console_dialog_alloc(const char_u *message, char_u *buttons, bool
/// The hotkeys can be multi-byte characters, but without combining chars.
///
/// @return an allocated string with hotkeys.
-static char_u *msg_show_console_dialog(char_u *message, char_u *buttons, int dfltbutton)
+static char *msg_show_console_dialog(char *message, char *buttons, int dfltbutton)
FUNC_ATTR_NONNULL_RET
{
bool has_hotkey[HAS_HOTKEY_LEN] = { false };
- char_u *hotk = console_dialog_alloc(message, buttons, has_hotkey);
+ char *hotk = console_dialog_alloc(message, buttons, has_hotkey);
copy_hotkeys_and_msg(message, buttons, dfltbutton, has_hotkey, hotk);
@@ -3711,13 +3679,13 @@ static char_u *msg_show_console_dialog(char_u *message, char_u *buttons, int dfl
/// @param has_hotkey An element in this array is true if corresponding button
/// has a hotkey
/// @param[out] hotkeys_ptr Pointer to the memory location where hotkeys will be copied
-static void copy_hotkeys_and_msg(const char_u *message, char_u *buttons, int default_button_idx,
- const bool has_hotkey[], char_u *hotkeys_ptr)
+static void copy_hotkeys_and_msg(const char *message, char *buttons, int default_button_idx,
+ const bool has_hotkey[], char *hotkeys_ptr)
{
*confirm_msg = '\n';
STRCPY(confirm_msg + 1, message);
- char_u *msgp = confirm_msg + 1 + STRLEN(message);
+ char *msgp = confirm_msg + 1 + STRLEN(message);
// Define first default hotkey. Keep the hotkey string NUL
// terminated to avoid reading past the end.
@@ -3734,7 +3702,7 @@ static void copy_hotkeys_and_msg(const char_u *message, char_u *buttons, int def
}
int idx = 0;
- char_u *r = buttons;
+ char *r = buttons;
while (*r) {
if (*r == DLG_BUTTON_SEP) {
*msgp++ = ',';
@@ -3790,28 +3758,28 @@ void display_confirm_msg(void)
confirm_msg_used++;
if (confirm_msg != NULL) {
msg_ext_set_kind("confirm");
- msg_puts_attr((const char *)confirm_msg, HL_ATTR(HLF_M));
+ msg_puts_attr(confirm_msg, HL_ATTR(HLF_M));
}
confirm_msg_used--;
}
-int vim_dialog_yesno(int type, char_u *title, char_u *message, int dflt)
+int vim_dialog_yesno(int type, char *title, char *message, int dflt)
{
if (do_dialog(type,
- title == NULL ? (char_u *)_("Question") : title,
+ title == NULL ? _("Question") : title,
message,
- (char_u *)_("&Yes\n&No"), dflt, NULL, FALSE) == 1) {
+ _("&Yes\n&No"), dflt, NULL, false) == 1) {
return VIM_YES;
}
return VIM_NO;
}
-int vim_dialog_yesnocancel(int type, char_u *title, char_u *message, int dflt)
+int vim_dialog_yesnocancel(int type, char *title, char *message, int dflt)
{
switch (do_dialog(type,
- title == NULL ? (char_u *)_("Question") : title,
+ title == NULL ? _("Question") : title,
message,
- (char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL, FALSE)) {
+ _("&Yes\n&No\n&Cancel"), dflt, NULL, false)) {
case 1:
return VIM_YES;
case 2:
@@ -3820,13 +3788,13 @@ int vim_dialog_yesnocancel(int type, char_u *title, char_u *message, int dflt)
return VIM_CANCEL;
}
-int vim_dialog_yesnoallcancel(int type, char_u *title, char_u *message, int dflt)
+int vim_dialog_yesnoallcancel(int type, char *title, char *message, int dflt)
{
switch (do_dialog(type,
- title == NULL ? (char_u *)"Question" : title,
+ title == NULL ? "Question" : title,
message,
- (char_u *)_("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"),
- dflt, NULL, FALSE)) {
+ _("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"),
+ dflt, NULL, false)) {
case 1:
return VIM_YES;
case 2:
diff --git a/src/nvim/message.h b/src/nvim/message.h
index 2de2890213..811e621c11 100644
--- a/src/nvim/message.h
+++ b/src/nvim/message.h
@@ -11,9 +11,7 @@
#include "nvim/macros.h"
#include "nvim/types.h"
-/*
- * Types of dialogs passed to do_dialog().
- */
+// Types of dialogs passed to do_dialog().
#define VIM_GENERIC 0
#define VIM_ERROR 1
#define VIM_WARNING 2
@@ -21,9 +19,7 @@
#define VIM_QUESTION 4
#define VIM_LAST_TYPE 4 // sentinel value
-/*
- * Return values for functions like vim_dialogyesno()
- */
+// Return values for functions like vim_dialogyesno()
#define VIM_YES 2
#define VIM_NO 3
#define VIM_CANCEL 4
@@ -40,7 +36,7 @@ typedef kvec_t(HlMessageChunk) HlMessage;
/// Message history for `:messages`
typedef struct msg_hist {
struct msg_hist *next; ///< Next message.
- char_u *msg; ///< Message text.
+ char *msg; ///< Message text.
const char *kind; ///< Message kind (for msg_ext)
int attr; ///< Message highlighting.
bool multiline; ///< Multiline message.
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index a8d0b3b584..7b267d6ce4 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 = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
+ chartabsize_T cts;
+ init_chartabsize_arg(&cts, wp, lnum, 0, (char *)line, (char *)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'.
@@ -664,10 +666,10 @@ void set_mouse_topline(win_T *wp)
static colnr_T scroll_line_len(linenr_T lnum)
{
colnr_T col = 0;
- char_u *line = ml_get(lnum);
+ char_u *line = (char_u *)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;
}
}
@@ -769,7 +771,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
// highlighting the second byte, not the ninth.
linenr_T lnum = wp->w_cursor.lnum;
- char_u *line = ml_get(lnum);
+ char_u *line = (char_u *)ml_get(lnum);
char_u *ptr = line;
char_u *ptr_end;
char_u *ptr_row_offset = line; // Where we begin adjusting `ptr_end`
@@ -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..481746881b 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -1,16 +1,14 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * move.c: Functions for moving the cursor and scrolling text.
- *
- * There are two ways to move the cursor:
- * 1. Move the cursor directly, the text is scrolled to keep the cursor in the
- * window.
- * 2. Scroll the text, the cursor is moved into the text visible in the
- * window.
- * The 'scrolloff' option makes this a bit complicated.
- */
+// move.c: Functions for moving the cursor and scrolling text.
+//
+// There are two ways to move the cursor:
+// 1. Move the cursor directly, the text is scrolled to keep the cursor in the
+// window.
+// 2. Scroll the text, the cursor is moved into the text visible in the
+// window.
+// The 'scrolloff' option makes this a bit complicated.
#include <assert.h>
#include <inttypes.h>
@@ -23,12 +21,15 @@
#include "nvim/diff.h"
#include "nvim/drawscreen.h"
#include "nvim/edit.h"
+#include "nvim/eval.h"
+#include "nvim/eval/typval.h"
#include "nvim/fold.h"
#include "nvim/getchar.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
+#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/plines.h"
@@ -47,19 +48,15 @@ typedef struct {
# include "move.c.generated.h"
#endif
-/*
- * Compute wp->w_botline for the current wp->w_topline. Can be called after
- * wp->w_topline changed.
- */
+// Compute wp->w_botline for the current wp->w_topline. Can be called after
+// wp->w_topline changed.
static void comp_botline(win_T *wp)
{
linenr_T lnum;
int done;
- /*
- * If w_cline_row is valid, start there.
- * Otherwise have to start at w_topline.
- */
+ // If w_cline_row is valid, start there.
+ // Otherwise have to start at w_topline.
check_cursor_moved(wp);
if (wp->w_valid & VALID_CROW) {
lnum = wp->w_cursor.lnum;
@@ -105,7 +102,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 +115,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
@@ -133,10 +130,8 @@ static void redraw_for_cursorcolumn(win_T *wp)
}
}
-/*
- * Update curwin->w_topline and redraw if necessary.
- * Used to update the screen before printing a message.
- */
+// Update curwin->w_topline and redraw if necessary.
+// Used to update the screen before printing a message.
void update_topline_redraw(void)
{
update_topline(curwin);
@@ -145,9 +140,7 @@ void update_topline_redraw(void)
}
}
-/*
- * Update curwin->w_topline to move the cursor onto the screen.
- */
+// Update curwin->w_topline to move the cursor onto the screen.
void update_topline(win_T *wp)
{
linenr_T old_topline;
@@ -184,7 +177,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;
@@ -250,14 +243,12 @@ void update_topline(win_T *wp)
}
}
- /*
- * If the cursor is below the bottom of the window, scroll the window
- * to put the cursor on the window.
- * When w_botline is invalid, recompute it first, to avoid a redraw later.
- * If w_botline was approximated, we might need a redraw later in a few
- * cases, but we don't want to spend (a lot of) time recomputing w_botline
- * for every small change.
- */
+ // If the cursor is below the bottom of the window, scroll the window
+ // to put the cursor on the window.
+ // When w_botline is invalid, recompute it first, to avoid a redraw later.
+ // If w_botline was approximated, we might need a redraw later in a few
+ // cases, but we don't want to spend (a lot of) time recomputing w_botline
+ // for every small change.
if (check_botline) {
if (!(wp->w_valid & VALID_BOTLINE_AP)) {
validate_botline(wp);
@@ -328,17 +319,15 @@ void update_topline(win_T *wp)
wp->w_viewport_invalid = true;
win_check_anchored_floats(wp);
- /*
- * Need to redraw when topline changed.
- */
+ // Need to redraw when topline changed.
if (wp->w_topline != old_topline
|| wp->w_topfill != old_topfill) {
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) {
@@ -349,9 +338,7 @@ void update_topline(win_T *wp)
*so_ptr = save_so;
}
-/*
- * Update win->w_topline to move the cursor onto the screen.
- */
+// Update win->w_topline to move the cursor onto the screen.
void update_topline_win(win_T *win)
{
switchwin_T switchwin;
@@ -360,11 +347,9 @@ void update_topline_win(win_T *win)
restore_win(&switchwin, true);
}
-/*
- * Return the scrolljump value to use for the current window.
- * When 'scrolljump' is positive use it as-is.
- * When 'scrolljump' is negative use it as a percentage of the window height.
- */
+// Return the scrolljump value to use for the current window.
+// When 'scrolljump' is positive use it as-is.
+// When 'scrolljump' is negative use it as a percentage of the window height.
static int scrolljump_value(void)
{
long result = p_sj >= 0 ? p_sj : (curwin->w_height_inner * -p_sj) / 100;
@@ -372,10 +357,8 @@ static int scrolljump_value(void)
return (int)result;
}
-/*
- * Return true when there are not 'scrolloff' lines above the cursor for the
- * current window.
- */
+// Return true when there are not 'scrolloff' lines above the cursor for the
+// current window.
static bool check_top_offset(void)
{
long so = get_scrolloff_value(curwin);
@@ -412,9 +395,7 @@ void update_curswant(void)
}
}
-/*
- * Check if the cursor has moved. Set the w_valid flag accordingly.
- */
+// Check if the cursor has moved. Set the w_valid flag accordingly.
void check_cursor_moved(win_T *wp)
{
if (wp->w_cursor.lnum != wp->w_valid_cursor.lnum) {
@@ -435,11 +416,9 @@ void check_cursor_moved(win_T *wp)
}
}
-/*
- * Call this function when some window settings have changed, which require
- * the cursor position, botline and topline to be recomputed and the window to
- * be redrawn. E.g, when changing the 'wrap' option or folding.
- */
+// Call this function when some window settings have changed, which require
+// the cursor position, botline and topline to be recomputed and the window to
+// be redrawn. E.g, when changing the 'wrap' option or folding.
void changed_window_setting(void)
{
changed_window_setting_win(curwin);
@@ -450,12 +429,10 @@ 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);
}
-/*
- * Set wp->w_topline to a certain number.
- */
+// Set wp->w_topline to a certain number.
void set_topline(win_T *wp, linenr_T lnum)
{
linenr_T prev_topline = wp->w_topline;
@@ -472,14 +449,12 @@ 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);
}
-/*
- * Call this function when the length of the cursor line (in screen
- * characters) has changed, and the change is before the cursor.
- * Need to take care of w_botline separately!
- */
+// Call this function when the length of the cursor line (in screen
+// characters) has changed, and the change is before the cursor.
+// Need to take care of w_botline separately!
void changed_cline_bef_curs(void)
{
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL
@@ -492,11 +467,9 @@ void changed_cline_bef_curs_win(win_T *wp)
|VALID_CHEIGHT|VALID_TOPLINE);
}
-/*
- * Call this function when the length of a line (in screen characters) above
- * the cursor have changed.
- * Need to take care of w_botline separately!
- */
+// Call this function when the length of a line (in screen characters) above
+// the cursor have changed.
+// Need to take care of w_botline separately!
void changed_line_abv_curs(void)
{
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL|VALID_CROW
@@ -509,9 +482,7 @@ void changed_line_abv_curs_win(win_T *wp)
|VALID_CHEIGHT|VALID_TOPLINE);
}
-/*
- * Make sure the value of curwin->w_botline is valid.
- */
+// Make sure the value of curwin->w_botline is valid.
void validate_botline(win_T *wp)
{
if (!(wp->w_valid & VALID_BOTLINE)) {
@@ -519,9 +490,7 @@ void validate_botline(win_T *wp)
}
}
-/*
- * Mark curwin->w_botline as invalid (because of some change in the buffer).
- */
+// Mark curwin->w_botline as invalid (because of some change in the buffer).
void invalidate_botline(void)
{
curwin->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP);
@@ -537,9 +506,7 @@ void approximate_botline_win(win_T *wp)
wp->w_valid &= ~VALID_BOTLINE;
}
-/*
- * Return true if curwin->w_wrow and curwin->w_wcol are valid.
- */
+// Return true if curwin->w_wrow and curwin->w_wcol are valid.
int cursor_valid(void)
{
check_cursor_moved(curwin);
@@ -547,10 +514,8 @@ int cursor_valid(void)
(VALID_WROW|VALID_WCOL);
}
-/*
- * Validate cursor position. Makes sure w_wrow and w_wcol are valid.
- * w_topline must be valid, you may need to call update_topline() first!
- */
+// Validate cursor position. Makes sure w_wrow and w_wcol are valid.
+// w_topline must be valid, you may need to call update_topline() first!
void validate_cursor(void)
{
check_cursor_moved(curwin);
@@ -559,10 +524,8 @@ void validate_cursor(void)
}
}
-/*
- * Compute wp->w_cline_row and wp->w_cline_height, based on the current value
- * of wp->w_topline.
- */
+// Compute wp->w_cline_row and wp->w_cline_height, based on the current value
+// of wp->w_topline.
static void curs_rows(win_T *wp)
{
// Check if wp->w_lines[].wl_size is invalid
@@ -571,7 +534,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 +550,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))) {
@@ -633,17 +596,13 @@ static void curs_rows(win_T *wp)
wp->w_valid |= VALID_CROW|VALID_CHEIGHT;
}
-/*
- * Validate curwin->w_virtcol only.
- */
+// Validate curwin->w_virtcol only.
void validate_virtcol(void)
{
validate_virtcol_win(curwin);
}
-/*
- * Validate wp->w_virtcol only.
- */
+// Validate wp->w_virtcol only.
void validate_virtcol_win(win_T *wp)
{
check_cursor_moved(wp);
@@ -654,9 +613,7 @@ void validate_virtcol_win(win_T *wp)
}
}
-/*
- * Validate curwin->w_cline_height only.
- */
+// Validate curwin->w_cline_height only.
void validate_cheight(void)
{
check_cursor_moved(curwin);
@@ -668,9 +625,7 @@ void validate_cheight(void)
}
}
-/*
- * Validate w_wcol and w_virtcol only.
- */
+// Validate w_wcol and w_virtcol only.
void validate_cursor_col(void)
{
validate_virtcol();
@@ -697,10 +652,8 @@ void validate_cursor_col(void)
}
}
-/*
- * Compute offset of a window, occupied by absolute or relative line number,
- * fold column and sign column (these don't move when scrolling horizontally).
- */
+// Compute offset of a window, occupied by absolute or relative line number,
+// fold column and sign column (these don't move when scrolling horizontally).
int win_col_off(win_T *wp)
{
return ((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0)
@@ -714,11 +667,9 @@ int curwin_col_off(void)
return win_col_off(curwin);
}
-/*
- * Return the difference in column offset for the second screen line of a
- * wrapped line. It's 8 if 'number' or 'relativenumber' is on and 'n' is in
- * 'cpoptions'.
- */
+// Return the difference in column offset for the second screen line of a
+// wrapped line. It's 8 if 'number' or 'relativenumber' is on and 'n' is in
+// 'cpoptions'.
int win_col_off2(win_T *wp)
{
if ((wp->w_p_nu || wp->w_p_rnu) && vim_strchr(p_cpo, CPO_NUMCOL) != NULL) {
@@ -746,9 +697,7 @@ void curs_columns(win_T *wp, int may_scroll)
long so = get_scrolloff_value(wp);
long siso = get_sidescrolloff_value(wp);
- /*
- * First make sure that w_topline is valid (after moving the cursor).
- */
+ // First make sure that w_topline is valid (after moving the cursor).
update_topline(wp);
// Next make sure that w_cline_row is valid.
@@ -756,9 +705,7 @@ void curs_columns(win_T *wp, int may_scroll)
curs_rows(wp);
}
- /*
- * Compute the number of virtual columns.
- */
+ // Compute the number of virtual columns.
if (wp->w_cline_folded) {
// In a folded line the cursor is always in the first column
startcol = wp->w_virtcol = endcol = wp->w_leftcol;
@@ -847,7 +794,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 +901,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);
@@ -1033,6 +980,62 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp,
*ecolp = ecol + coloff;
}
+/// "screenpos({winid}, {lnum}, {col})" function
+void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ tv_dict_alloc_ret(rettv);
+ dict_T *dict = rettv->vval.v_dict;
+
+ win_T *wp = find_win_by_nr_or_id(&argvars[0]);
+ if (wp == NULL) {
+ return;
+ }
+
+ pos_T pos = {
+ .lnum = (linenr_T)tv_get_number(&argvars[1]),
+ .col = (colnr_T)tv_get_number(&argvars[2]) - 1,
+ .coladd = 0
+ };
+ int row = 0;
+ int scol = 0, ccol = 0, ecol = 0;
+ textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false);
+
+ tv_dict_add_nr(dict, S_LEN("row"), row);
+ tv_dict_add_nr(dict, S_LEN("col"), scol);
+ tv_dict_add_nr(dict, S_LEN("curscol"), ccol);
+ tv_dict_add_nr(dict, S_LEN("endcol"), ecol);
+}
+
+/// "virtcol2col({winid}, {lnum}, {col})" function
+void f_virtcol2col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ rettv->vval.v_number = -1;
+
+ if (tv_check_for_number_arg(argvars, 0) == FAIL
+ || tv_check_for_number_arg(argvars, 1) == FAIL
+ || tv_check_for_number_arg(argvars, 2) == FAIL) {
+ return;
+ }
+
+ win_T *wp = find_win_by_nr_or_id(&argvars[0]);
+ if (wp == NULL) {
+ return;
+ }
+
+ bool error = false;
+ linenr_T lnum = (linenr_T)tv_get_number_chk(&argvars[1], &error);
+ if (error || lnum < 0 || lnum > wp->w_buffer->b_ml.ml_line_count) {
+ return;
+ }
+
+ int screencol = (int)tv_get_number_chk(&argvars[2], &error);
+ if (error || screencol < 0) {
+ return;
+ }
+
+ rettv->vval.v_number = vcol2col(wp, lnum, screencol);
+}
+
/// Scroll the current window down by "line_count" logical lines. "CTRL-Y"
///
/// @param line_count number of lines to scroll
@@ -1053,7 +1056,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 +1071,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
@@ -1079,10 +1082,8 @@ bool scrolldown(long line_count, int byfold)
}
check_topfill(curwin, true);
- /*
- * Compute the row number of the last row of the cursor line
- * and move the cursor onto the displayed part of the window.
- */
+ // Compute the row number of the last row of the cursor line
+ // and move the cursor onto the displayed part of the window.
int wrow = curwin->w_wrow;
if (curwin->w_p_wrap && curwin->w_width_inner != 0) {
validate_virtcol();
@@ -1130,7 +1131,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 +1188,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;
@@ -1200,10 +1201,8 @@ void check_topfill(win_T *wp, bool down)
win_check_anchored_floats(curwin);
}
-/*
- * Use as many filler lines as possible for w_topline. Make sure w_topline
- * is still visible.
- */
+// Use as many filler lines as possible for w_topline. Make sure w_topline
+// is still visible.
static void max_topfill(void)
{
int n = plines_win_nofill(curwin, curwin->w_topline, true);
@@ -1217,10 +1216,8 @@ static void max_topfill(void)
}
}
-/*
- * Scroll the screen one line down, but don't do it if it would move the
- * cursor off the screen.
- */
+// Scroll the screen one line down, but don't do it if it would move the
+// cursor off the screen.
void scrolldown_clamp(void)
{
int can_fill = (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline));
@@ -1249,22 +1246,20 @@ 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);
}
}
-/*
- * Scroll the screen one line up, but don't do it if it would move the cursor
- * off the screen.
- */
+// Scroll the screen one line up, but don't do it if it would move the cursor
+// off the screen.
void scrollup_clamp(void)
{
if (curwin->w_topline == curbuf->b_ml.ml_line_count
@@ -1296,12 +1291,10 @@ void scrollup_clamp(void)
}
}
-/*
- * Add one line above "lp->lnum". This can be a filler line, a closed fold or
- * a (wrapped) text line. Uses and sets "lp->fill".
- * Returns the height of the added line in "lp->height".
- * Lines above the first one are incredibly high: MAXCOL.
- */
+// Add one line above "lp->lnum". This can be a filler line, a closed fold or
+// a (wrapped) text line. Uses and sets "lp->fill".
+// Returns the height of the added line in "lp->height".
+// Lines above the first one are incredibly high: MAXCOL.
static void topline_back(win_T *wp, lineoff_T *lp)
{
if (lp->fill < win_get_fill(wp, lp->lnum)) {
@@ -1309,7 +1302,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;
@@ -1322,12 +1315,10 @@ static void topline_back(win_T *wp, lineoff_T *lp)
}
}
-/*
- * Add one line below "lp->lnum". This can be a filler line, a closed fold or
- * a (wrapped) text line. Uses and sets "lp->fill".
- * Returns the height of the added line in "lp->height".
- * Lines below the last one are incredibly high.
- */
+// Add one line below "lp->lnum". This can be a filler line, a closed fold or
+// a (wrapped) text line. Uses and sets "lp->fill".
+// Returns the height of the added line in "lp->height".
+// Lines below the last one are incredibly high.
static void botline_forw(win_T *wp, lineoff_T *lp)
{
if (lp->fill < win_get_fill(wp, lp->lnum + 1)) {
@@ -1335,7 +1326,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) {
@@ -1349,11 +1340,9 @@ static void botline_forw(win_T *wp, lineoff_T *lp)
}
}
-/*
- * Switch from including filler lines below lp->lnum to including filler
- * lines above loff.lnum + 1. This keeps pointing to the same line.
- * When there are no filler lines nothing changes.
- */
+// Switch from including filler lines below lp->lnum to including filler
+// lines above loff.lnum + 1. This keeps pointing to the same line.
+// When there are no filler lines nothing changes.
static void botline_topline(lineoff_T *lp)
{
if (lp->fill > 0) {
@@ -1362,11 +1351,9 @@ static void botline_topline(lineoff_T *lp)
}
}
-/*
- * Switch from including filler lines above lp->lnum to including filler
- * lines below loff.lnum - 1. This keeps pointing to the same line.
- * When there are no filler lines nothing changes.
- */
+// Switch from including filler lines above lp->lnum to including filler
+// lines below loff.lnum - 1. This keeps pointing to the same line.
+// When there are no filler lines nothing changes.
static void topline_botline(lineoff_T *lp)
{
if (lp->fill > 0) {
@@ -1375,11 +1362,9 @@ static void topline_botline(lineoff_T *lp)
}
}
-/*
- * Recompute topline to put the cursor at the top of the window.
- * Scroll at least "min_scroll" lines.
- * If "always" is true, always set topline (for "zt").
- */
+// Recompute topline to put the cursor at the top of the window.
+// Scroll at least "min_scroll" lines.
+// If "always" is true, always set topline (for "zt").
void scroll_cursor_top(int min_scroll, int always)
{
int scrolled = 0;
@@ -1394,13 +1379,11 @@ void scroll_cursor_top(int min_scroll, int always)
off = mouse_dragging - 1;
}
- /*
- * Decrease topline until:
- * - it has become 1
- * - (part of) the cursor line is moved off the screen or
- * - moved at least 'scrolljump' lines and
- * - at least 'scrolloff' lines above and below the cursor
- */
+ // Decrease topline until:
+ // - it has become 1
+ // - (part of) the cursor line is moved off the screen or
+ // - moved at least 'scrolljump' lines and
+ // - at least 'scrolloff' lines above and below the cursor
validate_cheight();
int used = curwin->w_cline_height; // includes filler lines above
if (curwin->w_cursor.lnum < curwin->w_topline) {
@@ -1421,10 +1404,8 @@ void scroll_cursor_top(int min_scroll, int always)
// Hide filler lines above cursor line by adding them to "extra".
int extra = win_get_fill(curwin, curwin->w_cursor.lnum);
- /*
- * Check if the lines from "top" to "bot" fit in the window. If they do,
- * set new_topline and advance "top" and "bot" to include more lines.
- */
+ // Check if the lines from "top" to "bot" fit in the window. If they do,
+ // set new_topline and advance "top" and "bot" to include more lines.
while (top > 0) {
int i = hasFolding(top, &top, NULL)
? 1 // count one logical line for a sequence of folded lines
@@ -1445,9 +1426,7 @@ void scroll_cursor_top(int min_scroll, int always)
scrolled += i;
}
- /*
- * If scrolling is needed, scroll at least 'sj' lines.
- */
+ // If scrolling is needed, scroll at least 'sj' lines.
if ((new_topline >= curwin->w_topline || scrolled > min_scroll)
&& extra >= off) {
break;
@@ -1459,18 +1438,14 @@ void scroll_cursor_top(int min_scroll, int always)
bot++;
}
- /*
- * If we don't have enough space, put cursor in the middle.
- * This makes sure we get the same position when using "k" and "j"
- * in a small window.
- */
+ // If we don't have enough space, put cursor in the middle.
+ // This makes sure we get the same position when using "k" and "j"
+ // in a small window.
if (used > curwin->w_height_inner) {
scroll_cursor_halfway(false);
} else {
- /*
- * If "always" is false, only adjust topline to a lower value, higher
- * value may happen with wrapping lines
- */
+ // If "always" is false, only adjust topline to a lower value, higher
+ // value may happen with wrapping lines
if (new_topline < curwin->w_topline || always) {
curwin->w_topline = new_topline;
}
@@ -1495,10 +1470,8 @@ void scroll_cursor_top(int min_scroll, int always)
}
}
-/*
- * Set w_empty_rows and w_filler_rows for window "wp", having used up "used"
- * screen lines for text lines.
- */
+// Set w_empty_rows and w_filler_rows for window "wp", having used up "used"
+// screen lines for text lines.
void set_empty_rows(win_T *wp, int used)
{
wp->w_filler_rows = 0;
@@ -1577,13 +1550,11 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
}
}
- /*
- * Stop counting lines to scroll when
- * - hitting start of the file
- * - scrolled nothing or at least 'sj' lines
- * - at least 'so' lines below the cursor
- * - lines between botline and cursor have been counted
- */
+ // Stop counting lines to scroll when
+ // - hitting start of the file
+ // - scrolled nothing or at least 'sj' lines
+ // - at least 'so' lines below the cursor
+ // - lines between botline and cursor have been counted
if (!hasFolding(curwin->w_cursor.lnum, &loff.lnum, &boff.lnum)) {
loff.lnum = cln;
boff.lnum = cln;
@@ -1673,21 +1644,17 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
}
}
- /*
- * Scroll up if the cursor is off the bottom of the screen a bit.
- * Otherwise put it at 1/2 of the screen.
- */
+ // Scroll up if the cursor is off the bottom of the screen a bit.
+ // Otherwise put it at 1/2 of the screen.
if (line_count >= curwin->w_height_inner && line_count > min_scroll) {
scroll_cursor_halfway(false);
} else {
scrollup(line_count, true);
}
- /*
- * If topline didn't change we need to restore w_botline and w_empty_rows
- * (we changed them).
- * If topline did change, update_screen() will set botline.
- */
+ // If topline didn't change we need to restore w_botline and w_empty_rows
+ // (we changed them).
+ // If topline did change, update_screen() will set botline.
if (curwin->w_topline == old_topline && set_topbot) {
curwin->w_botline = old_botline;
curwin->w_empty_rows = old_empty_rows;
@@ -1726,7 +1693,7 @@ void scroll_cursor_halfway(int atend)
}
below += boff.height;
} else {
- ++below; // count a "~" line
+ below++; // count a "~" line
if (atend) {
used++;
}
@@ -1760,18 +1727,14 @@ void scroll_cursor_halfway(int atend)
curwin->w_valid |= VALID_TOPLINE;
}
-/*
- * Correct the cursor position so that it is in a part of the screen at least
- * 'so' lines from the top and bottom, if possible.
- * If not possible, put it at the same position as scroll_cursor_halfway().
- * When called topline must be valid!
- */
+// Correct the cursor position so that it is in a part of the screen at least
+// 'so' lines from the top and bottom, if possible.
+// If not possible, put it at the same position as scroll_cursor_halfway().
+// When called topline must be valid!
void cursor_correct(void)
{
- /*
- * How many lines we would like to have above/below the cursor depends on
- * whether the first/last line of the file is on screen.
- */
+ // How many lines we would like to have above/below the cursor depends on
+ // whether the first/last line of the file is on screen.
int above_wanted = (int)get_scrolloff_value(curwin);
int below_wanted = (int)get_scrolloff_value(curwin);
if (mouse_dragging > 0) {
@@ -1795,10 +1758,8 @@ void cursor_correct(void)
}
}
- /*
- * If there are sufficient file-lines above and below the cursor, we can
- * return now.
- */
+ // If there are sufficient file-lines above and below the cursor, we can
+ // return now.
linenr_T cln = curwin->w_cursor.lnum; // Cursor Line Number
if (cln >= curwin->w_topline + above_wanted
&& cln < curwin->w_botline - below_wanted
@@ -1806,12 +1767,10 @@ void cursor_correct(void)
return;
}
- /*
- * Narrow down the area where the cursor can be put by taking lines from
- * the top and the bottom until:
- * - the desired context lines are found
- * - the lines from the top is past the lines from the bottom
- */
+ // Narrow down the area where the cursor can be put by taking lines from
+ // the top and the bottom until:
+ // - the desired context lines are found
+ // - the lines from the top is past the lines from the bottom
linenr_T topline = curwin->w_topline;
linenr_T botline = curwin->w_botline - 1;
// count filler lines as context
@@ -1860,11 +1819,9 @@ void cursor_correct(void)
curwin->w_viewport_invalid = true;
}
-/*
- * move screen 'count' pages up or down and update screen
- *
- * return FAIL for failure, OK otherwise
- */
+// move screen 'count' pages up or down and update screen
+//
+// return FAIL for failure, OK otherwise
int onepage(Direction dir, long count)
{
long n;
@@ -1899,7 +1856,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 +1892,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 +1957,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,22 +1997,20 @@ int onepage(Direction dir, long count)
}
}
- redraw_later(curwin, VALID);
+ redraw_later(curwin, UPD_VALID);
return retval;
}
-/*
- * Decide how much overlap to use for page-up or page-down scrolling.
- * This is symmetric, so that doing both keeps the same lines displayed.
- * Three lines are examined:
- *
- * before CTRL-F after CTRL-F / before CTRL-B
- * etc. l1
- * l1 last but one line ------------
- * l2 last text line l2 top text line
- * ------------- l3 second text line
- * l3 etc.
- */
+// Decide how much overlap to use for page-up or page-down scrolling.
+// This is symmetric, so that doing both keeps the same lines displayed.
+// Three lines are examined:
+//
+// before CTRL-F after CTRL-F / before CTRL-B
+// etc. l1
+// l1 last but one line ------------
+// l2 last text line l2 top text line
+// ------------- l3 second text line
+// l3 etc.
static void get_scroll_overlap(lineoff_T *lp, int dir)
{
int min_height = curwin->w_height_inner - 2;
@@ -2125,9 +2080,7 @@ void halfpage(bool flag, linenr_T Prenum)
validate_botline(curwin);
int room = curwin->w_empty_rows + curwin->w_filler_rows;
if (flag) {
- /*
- * scroll the text up
- */
+ // scroll the text up
while (n > 0 && curwin->w_botline <= curbuf->b_ml.ml_line_count) {
if (curwin->w_topfill > 0) {
i = 1;
@@ -2144,7 +2097,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 +2130,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;
@@ -2185,9 +2138,7 @@ void halfpage(bool flag, linenr_T Prenum)
check_cursor_lnum();
}
} else {
- /*
- * scroll the text down
- */
+ // scroll the text down
while (n > 0 && curwin->w_topline > 1) {
if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)) {
i = 1;
@@ -2199,7 +2150,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 +2158,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 +2169,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 +2183,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)
@@ -2247,9 +2198,7 @@ void do_check_cursorbind(void)
int old_VIsual_select = VIsual_select;
int old_VIsual_active = VIsual_active;
- /*
- * loop through the cursorbound windows
- */
+ // loop through the cursorbound windows
VIsual_select = VIsual_active = 0;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
curwin = wp;
@@ -2284,7 +2233,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) {
@@ -2294,9 +2243,7 @@ void do_check_cursorbind(void)
}
}
- /*
- * reset current-window
- */
+ // reset current-window
VIsual_select = old_VIsual_select;
VIsual_active = old_VIsual_active;
curwin = old_curwin;
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..326469bd38 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"
@@ -627,7 +629,7 @@ static void normal_redraw_mode_message(NormalState *s)
// If need to redraw, and there is a "keep_msg", redraw before the
// delay
if (must_redraw && keep_msg != NULL && !emsg_on_display) {
- char_u *kmsg;
+ char *kmsg;
kmsg = keep_msg;
keep_msg = NULL;
@@ -638,7 +640,7 @@ static void normal_redraw_mode_message(NormalState *s)
// now reset it, otherwise it's put in the history again
keep_msg = kmsg;
- kmsg = vim_strsave(keep_msg);
+ kmsg = xstrdup(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
@@ -1805,7 +1807,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
return false;
}
jump_flags = 0;
- if (STRCMP(p_mousem, "popup_setpos") == 0) {
+ if (strcmp(p_mousem, "popup_setpos") == 0) {
// First set the cursor position before showing the popup
// menu.
if (VIsual_active) {
@@ -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
@@ -2178,7 +2180,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
find_start_of_word(&VIsual);
if (*p_sel == 'e' && *get_cursor_pos_ptr() != NUL) {
curwin->w_cursor.col +=
- utfc_ptr2len((char *)get_cursor_pos_ptr());
+ utfc_ptr2len(get_cursor_pos_ptr());
}
find_end_of_word(&curwin->w_cursor);
}
@@ -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) {
@@ -2213,12 +2215,12 @@ static void find_start_of_word(pos_T *pos)
int cclass;
int col;
- line = ml_get(pos->lnum);
+ line = (char_u *)ml_get(pos->lnum);
cclass = get_mouse_class(line + pos->col);
while (pos->col > 0) {
col = pos->col - 1;
- col -= utf_head_off(line, line + col);
+ col -= utf_head_off((char *)line, (char *)line + col);
if (get_mouse_class(line + col) != cclass) {
break;
}
@@ -2234,10 +2236,10 @@ static void find_end_of_word(pos_T *pos)
int cclass;
int col;
- line = ml_get(pos->lnum);
+ line = (char_u *)ml_get(pos->lnum);
if (*p_sel == 'e' && pos->col > 0) {
pos->col--;
- pos->col -= utf_head_off(line, line + pos->col);
+ pos->col -= utf_head_off((char *)line, (char *)line + pos->col);
}
cclass = get_mouse_class(line + pos->col);
while (line[pos->col] != NUL) {
@@ -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;
}
}
@@ -2414,7 +2416,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text
// if i == 0: try to find an identifier
// if i == 1: try to find any non-white text
- char_u *ptr = ml_get_buf(wp->w_buffer, lnum, false);
+ char_u *ptr = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
for (i = (find_type & FIND_IDENT) ? 0 : 1; i < 2; i++) {
// 1. skip to start of identifier/text
col = startcol;
@@ -2443,7 +2445,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text
this_class = mb_get_class(ptr + col);
}
while (col > 0 && this_class != 0) {
- prevcol = col - 1 - utf_head_off(ptr, ptr + col - 1);
+ prevcol = col - 1 - utf_head_off((char *)ptr, (char *)ptr + col - 1);
prev_class = mb_get_class(ptr + prevcol);
if (this_class != prev_class
&& (i == 0
@@ -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;
@@ -2673,9 +2675,9 @@ void clear_showcmd(void)
if (cursor_bot) {
s = ml_get_pos(&VIsual);
- e = get_cursor_pos_ptr();
+ e = (char_u *)get_cursor_pos_ptr();
} else {
- s = get_cursor_pos_ptr();
+ s = (char_u *)get_cursor_pos_ptr();
e = ml_get_pos(&VIsual);
}
while ((*p_sel != 'e') ? s <= e : s < e) {
@@ -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;
}
@@ -3134,7 +3134,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
} else {
par_pos = curwin->w_cursor;
while (curwin->w_cursor.lnum > 1
- && *skipwhite((char *)get_cursor_line_ptr()) != NUL) {
+ && *skipwhite(get_cursor_line_ptr()) != NUL) {
curwin->w_cursor.lnum--;
}
}
@@ -3171,13 +3171,13 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
}
break;
}
- if (get_leader_len((char *)get_cursor_line_ptr(), NULL, false, true) > 0) {
+ if (get_leader_len(get_cursor_line_ptr(), NULL, false, true) > 0) {
// Ignore this line, continue at start of next line.
curwin->w_cursor.lnum++;
curwin->w_cursor.col = 0;
continue;
}
- bool valid = is_ident(get_cursor_line_ptr(), curwin->w_cursor.col);
+ bool valid = is_ident((char_u *)get_cursor_line_ptr(), curwin->w_cursor.col);
// If the current position is not a valid identifier and a previous match is
// present, favor that one instead.
@@ -3232,7 +3232,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
/// @return true if able to move cursor, false otherwise.
static bool nv_screengo(oparg_T *oap, int dir, long dist)
{
- int linelen = linetabsize(get_cursor_line_ptr());
+ int linelen = linetabsize((char_u *)get_cursor_line_ptr());
bool retval = true;
bool atend = false;
int n;
@@ -3303,7 +3303,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
}
curwin->w_cursor.lnum--;
- linelen = linetabsize(get_cursor_line_ptr());
+ linelen = linetabsize((char_u *)get_cursor_line_ptr());
if (linelen > width1) {
int w = (((linelen - width1 - 1) / width2) + 1) * width2;
assert(curwin->w_curswant <= INT_MAX - w);
@@ -3339,7 +3339,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
if (curwin->w_curswant >= width1) {
curwin->w_curswant -= width2;
}
- linelen = linetabsize(get_cursor_line_ptr());
+ linelen = linetabsize((char_u *)get_cursor_line_ptr());
}
}
}
@@ -3361,7 +3361,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
virtcol -= vim_strsize((char *)get_showbreak_value(curwin));
}
- int c = utf_ptr2char((char *)get_cursor_pos_ptr());
+ int c = utf_ptr2char(get_cursor_pos_ptr());
if (dir == FORWARD && virtcol < curwin->w_curswant
&& (curwin->w_curswant <= (colnr_T)width1)
&& !vim_isprintc(c) && c > 255) {
@@ -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);
}
}
@@ -4164,7 +4164,7 @@ void do_nv_ident(int c1, int c2)
/// 'K' normal-mode command. Get the command to lookup the keyword under the
/// cursor.
-static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, char **ptr_arg,
+static size_t nv_K_getcmd(cmdarg_T *cap, char *kp, bool kp_help, bool kp_ex, char **ptr_arg,
size_t n, char *buf, size_t buf_size)
{
if (kp_help) {
@@ -4201,8 +4201,8 @@ static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, c
// When a count is given, turn it into a range. Is this
// really what we want?
- bool isman = (STRCMP(kp, "man") == 0);
- bool isman_s = (STRCMP(kp, "man -s") == 0);
+ bool isman = (strcmp(kp, "man") == 0);
+ bool isman_s = (strcmp(kp, "man -s") == 0);
if (cap->count0 != 0 && !(isman || isman_s)) {
snprintf(buf, buf_size, ".,.+%" PRId64, (int64_t)(cap->count0 - 1));
}
@@ -4234,12 +4234,12 @@ static size_t nv_K_getcmd(cmdarg_T *cap, char_u *kp, bool kp_help, bool kp_ex, c
static void nv_ident(cmdarg_T *cap)
{
char *ptr = NULL;
- char_u *p;
+ char *p;
size_t n = 0; // init for GCC
int cmdchar;
bool g_cmd; // "g" command
bool tag_cmd = false;
- char_u *aux_ptr;
+ char *aux_ptr;
if (cap->cmdchar == 'g') { // "g*", "g#", "g]" and "gCTRL-]"
cmdchar = cap->nchar;
@@ -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 *kp = *curbuf->b_p_kp == NUL ? (char *)p_kp : 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;
@@ -4295,7 +4294,7 @@ static void nv_ident(cmdarg_T *cap)
// Call setpcmark() first, so "*``" puts the cursor back where
// it was.
setpcmark();
- curwin->w_cursor.col = (colnr_T)(ptr - (char *)get_cursor_line_ptr());
+ curwin->w_cursor.col = (colnr_T)(ptr - get_cursor_line_ptr());
if (!g_cmd && vim_iswordp((char_u *)ptr)) {
STRCPY(buf, "\\<");
@@ -4337,10 +4336,10 @@ static void nv_ident(cmdarg_T *cap)
ptr = xstrnsave(ptr, n);
if (kp_ex) {
// Escape the argument properly for an Ex command
- p = (char_u *)vim_strsave_fnameescape((const char *)ptr, VSE_NONE);
+ p = vim_strsave_fnameescape((const char *)ptr, VSE_NONE);
} else {
// Escape the argument properly for a shell command
- p = vim_strsave_shellescape((char_u *)ptr, true, true);
+ p = (char *)vim_strsave_shellescape((char_u *)ptr, true, true);
}
xfree(ptr);
char *newbuf = xrealloc(buf, STRLEN(buf) + STRLEN(p) + 1);
@@ -4349,33 +4348,33 @@ static void nv_ident(cmdarg_T *cap)
xfree(p);
} else {
if (cmdchar == '*') {
- aux_ptr = (char_u *)(p_magic ? "/.*~[^$\\" : "/^$\\");
+ aux_ptr = (p_magic ? "/.*~[^$\\" : "/^$\\");
} else if (cmdchar == '#') {
- aux_ptr = (char_u *)(p_magic ? "/?.*~[^$\\" : "/?^$\\");
+ aux_ptr = (p_magic ? "/?.*~[^$\\" : "/?^$\\");
} else if (tag_cmd) {
if (curbuf->b_help) {
// ":help" handles unescaped argument
- aux_ptr = (char_u *)"";
+ aux_ptr = "";
} else {
- aux_ptr = (char_u *)"\\|\"\n[";
+ aux_ptr = "\\|\"\n[";
}
} else {
- aux_ptr = (char_u *)"\\|\"\n*?[";
+ aux_ptr = "\\|\"\n*?[";
}
- p = (char_u *)buf + STRLEN(buf);
+ p = buf + STRLEN(buf);
while (n-- > 0) {
// put a backslash before \ and some others
- if (vim_strchr((char *)aux_ptr, *ptr) != NULL) {
+ if (vim_strchr(aux_ptr, *ptr) != NULL) {
*p++ = '\\';
}
// When current byte is a part of multibyte character, copy all
// bytes of that character.
const size_t len = (size_t)(utfc_ptr2len(ptr) - 1);
for (size_t i = 0; i < len && n > 0; i++, n--) {
- *p++ = (char_u)(*ptr++);
+ *p++ = *ptr++;
}
- *p++ = (char_u)(*ptr++);
+ *p++ = *ptr++;
}
*p = NUL;
}
@@ -4383,16 +4382,15 @@ static void nv_ident(cmdarg_T *cap)
// Execute the command.
if (cmdchar == '*' || cmdchar == '#') {
if (!g_cmd
- && vim_iswordp(mb_prevptr(get_cursor_line_ptr(), (char_u *)ptr))) {
+ && vim_iswordp(mb_prevptr((char_u *)get_cursor_line_ptr(), (char_u *)ptr))) {
STRCAT(buf, "\\>");
}
// put pattern in search history
init_history();
- add_to_history(HIST_SEARCH, (char_u *)buf, true, NUL);
+ add_to_history(HIST_SEARCH, 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);
@@ -4427,7 +4425,7 @@ bool get_visual_text(cmdarg_T *cap, char **pp, size_t *lenp)
return false;
}
if (VIsual_mode == 'V') {
- *pp = (char *)get_cursor_line_ptr();
+ *pp = get_cursor_line_ptr();
*lenp = STRLEN(*pp);
} else {
if (lt(curwin->w_cursor, VIsual)) {
@@ -4453,7 +4451,7 @@ bool get_visual_text(cmdarg_T *cap, char **pp, size_t *lenp)
static void nv_tagpop(cmdarg_T *cap)
{
if (!checkclearopq(cap->oap)) {
- do_tag((char_u *)"", DT_POP, (int)cap->count1, false, true);
+ do_tag("", DT_POP, (int)cap->count1, false, true);
}
}
@@ -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
@@ -4602,7 +4600,7 @@ static void nv_right(cmdarg_T *cap)
if (virtual_active()) {
oneright();
} else {
- curwin->w_cursor.col += utfc_ptr2len((char *)get_cursor_pos_ptr());
+ curwin->w_cursor.col += utfc_ptr2len(get_cursor_pos_ptr());
}
}
}
@@ -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);
@@ -4650,7 +4648,7 @@ static void nv_left(cmdarg_T *cap)
// Don't adjust op_end now, otherwise it won't work.
if ((cap->oap->op_type == OP_DELETE || cap->oap->op_type == OP_CHANGE)
&& !LINEEMPTY(curwin->w_cursor.lnum)) {
- char_u *cp = get_cursor_pos_ptr();
+ char_u *cp = (char_u *)get_cursor_pos_ptr();
if (*cp != NUL) {
curwin->w_cursor.col += utfc_ptr2len((char *)cp);
@@ -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;
}
@@ -5363,7 +5360,7 @@ static void nv_replace(cmdarg_T *cap)
}
// Abort if not enough characters to replace.
- ptr = get_cursor_pos_ptr();
+ ptr = (char_u *)get_cursor_pos_ptr();
if (STRLEN(ptr) < (unsigned)cap->count1
|| (mb_charlen(ptr) < cap->count1)) {
clearopbeep(cap->oap);
@@ -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();
}
@@ -6071,7 +6068,7 @@ static void nv_g_underscore_cmd(cmdarg_T *cap)
return;
}
- char_u *ptr = get_cursor_line_ptr();
+ char_u *ptr = (char_u *)get_cursor_line_ptr();
// In Visual mode we may end up after the line.
if (curwin->w_cursor.col > 0 && ptr[curwin->w_cursor.col] == NUL) {
@@ -6282,7 +6279,7 @@ static void nv_g_cmd(cmdarg_T *cap)
case 'M':
oap->motion_type = kMTCharWise;
oap->inclusive = false;
- i = linetabsize(get_cursor_line_ptr());
+ i = linetabsize((char_u *)get_cursor_line_ptr());
if (cap->count0 > 0 && cap->count0 <= 100) {
coladvance((colnr_T)(i * cap->count0 / 100));
} else {
@@ -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..0317080f4f 100644
--- a/src/nvim/normal.h
+++ b/src/nvim/normal.h
@@ -22,9 +22,7 @@ typedef enum {
kMTUnknown = -1, ///< Unknown or invalid motion type
} MotionType;
-/*
- * Arguments for operators.
- */
+// Arguments for operators.
typedef struct oparg_S {
int op_type; // current pending operator type
int regname; // register to use for the operator
@@ -53,11 +51,9 @@ typedef struct oparg_S {
// block
} oparg_T;
-/*
- * Arguments for Normal mode commands.
- */
+// 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 +65,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 3be4536f16..7dc6da8e1f 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1,10 +1,8 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * ops.c: implementation of various operators: op_shift, op_delete, op_tilde,
- * op_change, op_yank, do_put, do_join
- */
+// ops.c: implementation of various operators: op_shift, op_delete, op_tilde,
+// op_change, op_yank, do_put, do_join
#include <assert.h>
#include <inttypes.h>
@@ -21,6 +19,7 @@
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/userfunc.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_getln.h"
@@ -51,12 +50,29 @@
#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"
#include "nvim/window.h"
+#include "nvim/yankmap.h"
+
+struct yank_registers {
+ yankmap_T inner;
+};
+
+yank_registers_T y_regs;
-static yankreg_T y_regs[NUM_REGISTERS] = { 0 };
+static yankreg_T *get_reg(yank_registers_T *regs, int idx)
+{
+ return yankmap_get(&regs->inner, idx);
+
+}
+
+static yankreg_T *get_global_reg(int idx)
+{
+ return get_reg(&y_regs, idx);
+}
static yankreg_T *y_previous = NULL; // ptr to last written yankreg
@@ -66,10 +82,8 @@ static bool clipboard_delay_update = false; // delay clipboard update
static bool clipboard_needs_update = false; // clipboard was updated
static bool clipboard_didwarn = false;
-/*
- * structure used by block_prep, op_delete and op_yank for blockwise operators
- * also op_change, op_shift, op_insert, op_replace - AKelly
- */
+// structure used by block_prep, op_delete and op_yank for blockwise operators
+// also op_change, op_shift, op_insert, op_replace - AKelly
struct block_def {
int startspaces; // 'extra' cols before first char
int endspaces; // 'extra' cols after last char
@@ -78,9 +92,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
@@ -95,11 +109,9 @@ struct block_def {
#define OPF_LINES 1 // operator always works on lines
#define OPF_CHANGE 2 // operator changes text
-/*
- * The names of operators.
- * IMPORTANT: Index must correspond with defines in vim.h!!!
- * The third field indicates whether the operator always works on lines.
- */
+// The names of operators.
+// IMPORTANT: Index must correspond with defines in vim.h!!!
+// The third field indicates whether the operator always works on lines.
static char opchars[][3] =
{
{ NUL, NUL, 0 }, // OP_NOP
@@ -181,13 +193,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;
@@ -224,7 +236,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
}
for (i = oap->line_count - 1; i >= 0; i--) {
- first_char = *get_cursor_line_ptr();
+ first_char = (uint8_t)(*get_cursor_line_ptr());
if (first_char == NUL) { // empty line
curwin->w_cursor.col = 0;
} else if (oap->motion_type == kMTBlockWise) {
@@ -234,7 +246,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) {
@@ -244,7 +256,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();
@@ -271,7 +283,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
// Set "'[" and "']" marks.
curbuf->b_op_start = oap->start;
curbuf->b_op_end.lnum = oap->end.lnum;
- curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ curbuf->b_op_end.col = (colnr_T)strlen(ml_get(oap->end.lnum));
if (curbuf->b_op_end.col > 0) {
curbuf->b_op_end.col--;
}
@@ -355,17 +367,15 @@ static void shift_block(oparg_T *oap, int amount)
return; // multiplication overflow
}
- char_u *const oldp = get_cursor_line_ptr();
+ char_u *const oldp = (char_u *)get_cursor_line_ptr();
int startcol, oldlen, newlen;
if (!left) {
- /*
- * 1. Get start vcol
- * 2. Total ws vcols
- * 3. Divvy into TABs & spp
- * 4. Construct new string
- */
+ // 1. Get start vcol
+ // 2. Total ws vcols
+ // 3. Divvy into TABs & spp
+ // 4. Construct new string
total += bd.pre_whitesp; // all virtual WS up to & incl a split TAB
colnr_T ws_vcol = bd.start_vcol - bd.pre_whitesp;
char_u *old_textstart = bd.textstart;
@@ -377,12 +387,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, (char *)bd.textstart, (char *)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) {
@@ -419,13 +437,11 @@ static void shift_block(oparg_T *oap, int amount)
// block shift
char_u *non_white = bd.textstart;
- /*
- * Firstly, let's find the first non-whitespace character that is
- * displayed after the block's start column and the character's column
- * number. Also, let's calculate the width of all the whitespace
- * characters that are displayed in the block and precede the searched
- * non-whitespace character.
- */
+ // Firstly, let's find the first non-whitespace character that is
+ // displayed after the block's start column and the character's column
+ // number. Also, let's calculate the width of all the whitespace
+ // characters that are displayed in the block and precede the searched
+ // non-whitespace character.
// If "bd.startspaces" is set, "bd.textstart" points to the character,
// the part of which is displayed at the block's beginning. Let's start
@@ -437,10 +453,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, (char *)bd.textstart, (char *)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.
@@ -461,17 +483,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,
+ (char *)bd.textstart, (char *)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
@@ -526,7 +550,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def
continue; // OP_INSERT, line ends before block start
}
- oldp = ml_get(lnum);
+ oldp = (char_u *)ml_get(lnum);
if (b_insert) {
ts_val = bdp->start_char_vcols;
@@ -555,7 +579,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def
if (spaces > 0) {
// avoid copying part of a multi-byte character
- offset -= utf_head_off(oldp, oldp + offset);
+ offset -= utf_head_off((char *)oldp, (char *)oldp + offset);
}
if (spaces < 0) { // can happen when the cursor was moved
spaces = 0;
@@ -651,7 +675,7 @@ void op_reindent(oparg_T *oap, Indenter how)
// indented, unless there is only one line.
if (i != oap->line_count - 1 || oap->line_count == 1
|| how != get_lisp_indent) {
- l = (char_u *)skipwhite((char *)get_cursor_line_ptr());
+ l = (char_u *)skipwhite(get_cursor_line_ptr());
if (*l == NUL) { // empty or blank line
amount = 0;
} else {
@@ -674,15 +698,15 @@ void op_reindent(oparg_T *oap, Indenter how)
curwin->w_cursor.lnum = start_lnum;
beginline(BL_SOL | BL_FIX);
- /* Mark changed lines so that they will be redrawn. When Visual
- * highlighting was present, need to continue until the last line. When
- * there is no change still need to remove the Visual highlighting. */
+ // Mark changed lines so that they will be redrawn. When Visual
+ // highlighting was present, need to continue until the last line. When
+ // there is no change still need to remove the Visual highlighting.
if (last_changed != 0) {
changed_lines(first_changed, 0,
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) {
@@ -698,9 +722,7 @@ void op_reindent(oparg_T *oap, Indenter how)
}
}
-/*
- * Keep the last expression line here, for repeating.
- */
+// Keep the last expression line here, for repeating.
static char_u *expr_line = NULL;
/// Get an expression for the "\"=expr1" or "CTRL-R =expr1"
@@ -717,56 +739,74 @@ int get_expr_register(void)
if (*new_line == NUL) { // use previous line
xfree(new_line);
} else {
- set_expr_line(new_line);
+ set_expr_line((char *)new_line);
}
return '=';
}
/// Set the expression for the '=' register.
/// Argument must be an allocated string.
-void set_expr_line(char_u *new_line)
+void set_expr_line(char *new_line)
{
xfree(expr_line);
- expr_line = new_line;
+ expr_line = (char_u *)new_line;
}
/// Get the result of the '=' register expression.
///
/// @return a pointer to allocated memory, or NULL for failure.
-char_u *get_expr_line(void)
+char *get_expr_line(void)
{
- char_u *expr_copy;
- char_u *rv;
+ char *expr_copy;
+ char *rv;
static int nested = 0;
if (expr_line == NULL) {
return NULL;
}
- /* Make a copy of the expression, because evaluating it may cause it to be
- * changed. */
- expr_copy = vim_strsave(expr_line);
+ // Make a copy of the expression, because evaluating it may cause it to be
+ // changed.
+ expr_copy = xstrdup((char *)expr_line);
- /* When we are invoked recursively limit the evaluation to 10 levels.
- * Then return the string as-is. */
+ // When we are invoked recursively limit the evaluation to 10 levels.
+ // Then return the string as-is.
if (nested >= 10) {
return expr_copy;
}
nested++;
- rv = (char_u *)eval_to_string((char *)expr_copy, NULL, true);
+ rv = eval_to_string(expr_copy, NULL, true);
nested--;
xfree(expr_copy);
return rv;
}
/// Get the '=' register expression itself, without evaluating it.
-char_u *get_expr_line_src(void)
+char *get_expr_line_src(void)
{
if (expr_line == NULL) {
return NULL;
}
- return vim_strsave(expr_line);
+ return xstrdup((char *)expr_line);
+}
+
+
+int get_userreg(int regname)
+{
+ if ((regname >= 'a' && regname <= 'z')
+ || (regname >= 'A' && regname <= 'Z')
+ || (regname >= '0' && regname <= '9')
+ || (regname <= 127 && strchr("\"-:.%#=*+_/", regname))
+ || regname == Ctrl_F
+ || regname == Ctrl_P
+ || regname == Ctrl_W
+ || regname == Ctrl_A
+ || (regname + USER_REGISTERS_START) < regname) {
+ return -1;
+ }
+
+ return regname + USER_REGISTERS_START;
}
/// @return whether `regname` is a valid name of a yank register.
@@ -785,12 +825,152 @@ bool valid_yank_reg(int regname, bool writing)
|| regname == '-'
|| regname == '_'
|| regname == '*'
- || regname == '+') {
+ || regname == '+'
+ || get_userreg(regname) != -1) {
return true;
}
return false;
}
+static int call_userreg_put(const char* urf, int regname, typval_T* out)
+{
+ char regname_str[5];
+ int len;
+
+ len = (*utf_char2len)(regname);
+ regname_str[len] = 0;
+ utf_char2bytes(regname, regname_str);
+
+ typval_T args[3];
+ args[0].v_type = VAR_STRING;
+ args[1].v_type = VAR_STRING;
+ args[2].v_type = VAR_NUMBER;
+
+ args[0].vval.v_string = "put";
+ args[1].vval.v_string = regname_str;
+ args[2].vval.v_number = 0;
+
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.evaluate = true;
+
+ return call_func(
+ urf,
+ -1,
+ out,
+ /* argcount_in = */ 3,
+ args,
+ &funcexe);
+}
+
+// Converts a typval returned from the userregfunction to a register.
+static void typval_to_yankreg(yankreg_T* yankreg, typval_T* val)
+{
+ if (!yankreg || !val) return;
+
+ char* type;
+ dict_T* dict;
+ typval_T tv;
+ size_t i;
+ size_t sz;
+
+ free_register(yankreg);
+ memset(yankreg, 0, sizeof(*yankreg));
+
+ switch (val->v_type) {
+
+ case VAR_DICT:
+ dict = val->vval.v_dict;
+ type = tv_dict_get_string(dict, "type", false);
+
+ if (!strcmp(type, "block")) {
+ yankreg->y_width = (int) tv_dict_get_number(dict, "width");
+ yankreg->y_type = kMTBlockWise;
+ } else if (!strcmp(type, "line")) {
+ yankreg->y_type = kMTLineWise;
+ } else {
+ yankreg->y_type = kMTCharWise;
+ }
+
+ if (tv_dict_get_tv(dict, "lines", &tv) == OK) {
+ if (tv.v_type == VAR_STRING) {
+ yankreg->y_array = xcalloc(sizeof(char*), 1);
+ yankreg->y_array[0] = strdup(tv.vval.v_string);
+ } else if (tv.v_type == VAR_LIST) {
+ yankreg->y_array =
+ xcalloc(sizeof(char*), (size_t) tv_list_len(tv.vval.v_list));
+
+ i = 0;
+ TV_LIST_ITER_CONST(tv.vval.v_list, li, {
+ if (li->li_tv.v_type == VAR_STRING) {
+ yankreg->y_array[i] = strdup(tv_get_string(&li->li_tv));
+ } else {
+ yankreg->y_array[i] = NULL;
+ }
+ ++ i;
+ });
+
+ yankreg->y_size = i;
+ }
+ } else {
+ yankreg->y_array = NULL;
+ }
+
+ if (tv_dict_get_tv(dict, "additional_data", &tv) == OK) {
+ if (tv.v_type == VAR_DICT) {
+ yankreg->additional_data = tv.vval.v_dict;
+ }
+ }
+ break;
+
+ case VAR_LIST:
+ yankreg->y_type = kMTLineWise;
+ sz = (size_t) tv_list_len(val->vval.v_list);
+ yankreg->y_array = xcalloc(sizeof(char*), sz);
+ yankreg->y_size = sz;
+ i = 0;
+ TV_LIST_ITER_CONST(val->vval.v_list, li, {
+ yankreg->y_array[i] = strdup(tv_get_string(&li->li_tv));
+ i ++;
+ });
+ break;
+
+ default:
+ yankreg->y_type = kMTCharWise;
+ yankreg->y_size = 1;
+
+ if (val->vval.v_string) {
+ yankreg->y_array = xcalloc(sizeof(char*), 1);
+ yankreg->y_array[0] = strdup(tv_get_string(val));
+ } else {
+ yankreg->y_array = NULL;
+ }
+
+ break;
+
+ }
+
+ yankreg->timestamp = os_time();
+}
+
+static void copy_userreg(yankreg_T* into, int regname)
+{
+ if (!into) return;
+
+ if (!curbuf->b_p_urf || strlen((char *) curbuf->b_p_urf) == 0)
+ return;
+
+
+ typval_T* ret = xmalloc(sizeof(typval_T));
+
+ if (call_userreg_put((const char*) curbuf->b_p_urf, regname, ret) == FAIL) {
+ return;
+ }
+
+ typval_to_yankreg(into, ret);
+
+ tv_free(ret);
+}
+
/// @return yankreg_T to use, according to the value of `regname`.
/// Cannot handle the '_' (black hole) register.
/// Must only be called with a valid register name!
@@ -820,6 +1000,10 @@ yankreg_T *get_yank_register(int regname, int mode)
&& (regname == 0 || regname == '"' || regname == '*' || regname == '+')
&& y_previous != NULL) {
// in case clipboard not available, paste from previous used register
+ if (get_userreg(y_previous->name) != -1) {
+ // If y_previous is a userreg, repeat the userreg copy.
+ copy_userreg(y_previous, y_previous->name);
+ }
return y_previous;
}
@@ -828,7 +1012,11 @@ yankreg_T *get_yank_register(int regname, int mode)
if (i == -1) {
i = 0;
}
- reg = &y_regs[i];
+ reg = get_global_reg(i);
+ if (get_userreg(regname) != -1 && mode != YREG_YANK) {
+ // If the mode is not yank, copy the userreg data to the reg.
+ copy_userreg(reg, regname);
+ }
if (mode == YREG_YANK) {
// remember the written register for unnamed paste
@@ -897,8 +1085,7 @@ int do_record(int c)
if (reg_recording == 0) {
// start recording
- // registers 0-9, a-z and " are allowed
- if (c < 0 || (!ASCII_ISALNUM(c) && c != '"')) {
+ if (c < 0) {
retval = FAIL;
} else {
reg_recording = c;
@@ -909,7 +1096,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;
}
@@ -930,9 +1117,10 @@ int do_record(int c)
}
// Name of requested register, or empty string for unnamed operation.
- char buf[NUMBUFLEN + 2];
- buf[0] = (char)regname;
- buf[1] = NUL;
+ char buf[NUMBUFLEN + 5];
+ int len = (*utf_char2len)(regname);
+ utf_char2bytes(regname, buf);
+ buf[len] = NUL;
(void)tv_dict_add_str(dict, S_LEN("regname"), buf);
tv_dict_set_keys_readonly(dict);
@@ -963,7 +1151,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;
@@ -997,7 +1185,7 @@ static int stuff_yank(int regname, char_u *p)
yankreg_T *reg = get_yank_register(regname, YREG_YANK);
if (is_append_register(regname) && reg->y_array != NULL) {
char **pp = &(reg->y_array[reg->y_size - 1]);
- char_u *lp = xmalloc(STRLEN(*pp) + STRLEN(p) + 1);
+ char_u *lp = xmalloc(strlen(*pp) + STRLEN(p) + 1);
STRCPY(lp, *pp);
// TODO(philix): use xstpcpy() in stuff_yank()
STRCAT(lp, p);
@@ -1013,6 +1201,9 @@ static int stuff_yank(int regname, char_u *p)
reg->y_type = kMTCharWise;
}
reg->timestamp = os_time();
+ if (get_userreg(regname) != -1) {
+ return eval_yank_userreg(curbuf->b_p_urf, regname, reg);
+ }
return OK;
}
@@ -1065,11 +1256,11 @@ static char_u *execreg_line_continuation(char **lines, size_t *idx)
}
}
ga_append(&ga, NUL);
- char_u *str = vim_strsave(ga.ga_data);
+ char *str = xstrdup(ga.ga_data);
ga_clear(&ga);
*idx = i;
- return str;
+ return (char_u *)str;
}
/// Execute a yank register: copy it into the stuff buffer
@@ -1110,7 +1301,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"
@@ -1125,7 +1316,7 @@ int do_execreg(int regname, int colon, int addcr, int silent)
}
xfree(p);
} else if (regname == '=') {
- p = get_expr_line();
+ p = (char_u *)get_expr_line();
if (p == NULL) {
return FAIL;
}
@@ -1148,9 +1339,7 @@ int do_execreg(int regname, int colon, int addcr, int silent)
// Disallow remapping for ":@r".
int remap = colon ? REMAP_NONE : REMAP_YES;
- /*
- * Insert lines into typeahead buffer, from last one to first one.
- */
+ // Insert lines into typeahead buffer, from last one to first one.
put_reedit_in_typebuf(silent);
char *escaped;
for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included
@@ -1260,11 +1449,9 @@ int insert_reg(int regname, bool literally_arg)
bool allocated;
const bool literally = literally_arg || is_literal_register(regname);
- /*
- * It is possible to get into an endless loop by having CTRL-R a in
- * register a and then, in insert mode, doing CTRL-R a.
- * If you hit CTRL-C, the loop will be broken here.
- */
+ // It is possible to get into an endless loop by having CTRL-R a in
+ // register a and then, in insert mode, doing CTRL-R a.
+ // If you hit CTRL-C, the loop will be broken here.
os_breakcheck();
if (got_int) {
return FAIL;
@@ -1311,32 +1498,77 @@ 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));
- }
+/// 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) {
+ dict_T *const dict = tv_dict_alloc();
+ dict->dv_refcount = 1;
+ tv_dict_add_nr(dict, S_LEN("width"), yankreg->y_width);
- // 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);
- }
+ const char* type;
+
+ switch(yankreg->y_type) {
+ case kMTLineWise:
+ type = "line";
+ break;
+ case kMTCharWise:
+ type = "char";
+ break;
+ case kMTBlockWise:
+ type = "block";
+ break;
+ default:
+ type = "unknown";
+ }
+
+ tv_dict_add_str(dict, S_LEN("type"), type);
+ if (yankreg->additional_data) {
+ tv_dict_add_dict(dict, S_LEN("additional_data"), yankreg->additional_data);
}
+
+ list_T *const lines = tv_list_alloc(yankreg->y_size);
+
+ size_t i;
+ for (i = 0; i < yankreg->y_size; ++ i) {
+ tv_list_append_string(
+ lines, yankreg->y_array[i], strlen(yankreg->y_array[i]));
+ }
+
+ tv_dict_add_list(dict, S_LEN("lines"), lines);
+
+ return dict;
+}
+
+/*
+ * Executes the yank() function on a user-defined register to set the contents
+ * of that register.
+ */
+static int eval_yank_userreg(const char_u *ufn, int regname, yankreg_T *reg)
+{
+ if (!reg)
+ return -1;
+
+ int ret, len;
+ char regname_str[5];
+
+ len = (*utf_char2len)(regname);
+ regname_str[len] = 0;
+ utf_char2bytes(regname, regname_str);
+
+ typval_T args[4];
+ args[0].v_type = VAR_STRING;
+ args[1].v_type = VAR_STRING;
+ args[2].v_type = VAR_DICT;
+ args[3].v_type = VAR_UNKNOWN;
+
+ args[0].vval.v_string = "yank";
+ args[1].vval.v_string = regname_str;
+ args[2].vval.v_dict = yankreg_to_dict(reg);
+
+ char *dup_ufn = strdup((char *)ufn);
+ ret = (int)call_func_retnr(dup_ufn, 3, args);
+ xfree(dup_ufn);
+ return ret;
}
/// If "regname" is a special register, return true and store a pointer to its
@@ -1365,7 +1597,7 @@ bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg)
return true;
case '=': // result of expression
- *argp = (char *)get_expr_line();
+ *argp = get_expr_line();
*allocated = true;
return true;
@@ -1373,7 +1605,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
@@ -1419,12 +1651,15 @@ bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg)
return false;
}
- *argp = (char *)ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum, false);
+ *argp = ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum, false);
return true;
case '_': // black hole: always empty
*argp = "";
return true;
+
+ default:
+ break;
}
return false;
@@ -1458,8 +1693,8 @@ bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr)
cmdline_paste_str((char_u *)"\r", literally);
}
- /* Check for CTRL-C, in case someone tries to paste a few thousand
- * lines and gets bored. */
+ // Check for CTRL-C, in case someone tries to paste a few thousand
+ // lines and gets bored.
os_breakcheck();
if (got_int) {
return FAIL;
@@ -1471,14 +1706,14 @@ bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr)
/// Shift the delete registers: "9 is cleared, "8 becomes "9, etc.
static void shift_delete_registers(bool y_append)
{
- free_register(&y_regs[9]); // free register "9
+ free_register(get_global_reg(9)); // free register "9
for (int n = 9; n > 1; n--) {
- y_regs[n] = y_regs[n - 1];
+ *get_global_reg(n) = *get_global_reg(n - 1);
}
if (!y_append) {
- y_previous = &y_regs[1];
+ y_previous = get_global_reg(1);
}
- y_regs[1].y_array = NULL; // set register "1 to empty
+ get_global_reg(1)->y_array = NULL; // set register "1 to empty
}
/// Handle a delete operation.
@@ -1514,17 +1749,15 @@ int op_delete(oparg_T *oap)
mb_adjust_opend(oap);
- /*
- * Imitate the strange Vi behaviour: If the delete spans more than one
- * line and motion_type == kMTCharWise and the result is a blank line, make the
- * delete linewise. Don't do this for the change command or Visual mode.
- */
+ // Imitate the strange Vi behaviour: If the delete spans more than one
+ // line and motion_type == kMTCharWise and the result is a blank line, make the
+ // delete linewise. Don't do this for the change command or Visual mode.
if (oap->motion_type == kMTCharWise
&& !oap->is_VIsual
&& oap->line_count > 1
&& oap->motion_force == NUL
&& oap->op_type == OP_DELETE) {
- ptr = ml_get(oap->end.lnum) + oap->end.col;
+ ptr = (char_u *)ml_get(oap->end.lnum) + oap->end.col;
if (*ptr != NUL) {
ptr += oap->inclusive;
}
@@ -1534,10 +1767,8 @@ int op_delete(oparg_T *oap)
}
}
- /*
- * Check for trying to delete (e.g. "D") in an empty line.
- * Note: For the change operator it is ok.
- */
+ // Check for trying to delete (e.g. "D") in an empty line.
+ // Note: For the change operator it is ok.
if (oap->motion_type != kMTLineWise
&& oap->line_count == 1
&& oap->op_type == OP_DELETE
@@ -1555,11 +1786,9 @@ int op_delete(oparg_T *oap)
return OK;
}
- /*
- * Do a yank of whatever we're about to delete.
- * If a yank register was specified, put the deleted text into that
- * register. For the black hole register '_' don't yank anything.
- */
+ // Do a yank of whatever we're about to delete.
+ // If a yank register was specified, put the deleted text into that
+ // register. For the black hole register '_' don't yank anything.
if (oap->regname != '_') {
yankreg_T *reg = NULL;
int did_yank = false;
@@ -1577,9 +1806,10 @@ 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 = &y_regs[1];
+ reg = get_global_reg(1);
op_yank_reg(oap, false, reg, false);
did_yank = true;
}
@@ -1602,9 +1832,7 @@ int op_delete(oparg_T *oap)
}
}
- /*
- * block mode delete
- */
+ // block mode delete
if (oap->motion_type == kMTBlockWise) {
if (u_save((linenr_T)(oap->start.lnum - 1),
(linenr_T)(oap->end.lnum + 1)) == FAIL) {
@@ -1627,7 +1855,7 @@ int op_delete(oparg_T *oap)
// If we delete a TAB, it may be replaced by several characters.
// Thus the number of characters may increase!
n = bd.textlen - bd.startspaces - bd.endspaces;
- oldp = ml_get(lnum);
+ oldp = (char_u *)ml_get(lnum);
newp = (char_u *)xmalloc(STRLEN(oldp) - (size_t)n + 1);
// copy up to deleted part
memmove(newp, oldp, (size_t)bd.textcol);
@@ -1672,7 +1900,7 @@ int op_delete(oparg_T *oap)
beginline(0); // cursor in column 0
}
- int old_len = (int)STRLEN(ml_get(curwin->w_cursor.lnum));
+ int old_len = (int)strlen(ml_get(curwin->w_cursor.lnum));
truncate_line(false); // delete the rest of the line
extmark_splice_cols(curbuf,
@@ -1745,7 +1973,7 @@ int op_delete(oparg_T *oap)
if (virtual_op) {
// fix up things for virtualedit-delete:
// break the tabs which are going to get in our way
- char_u *curline = get_cursor_line_ptr();
+ char_u *curline = (char_u *)get_cursor_line_ptr();
int len = (int)STRLEN(curline);
if (oap->end.coladd != 0
@@ -1826,7 +2054,7 @@ setmarks:
static void mb_adjust_opend(oparg_T *oap)
{
if (oap->inclusive) {
- char *p = (char *)ml_get(oap->end.lnum);
+ char *p = ml_get(oap->end.lnum);
oap->end.col += utf_cp_tail_off(p, p + oap->end.col);
}
}
@@ -1835,7 +2063,7 @@ static void mb_adjust_opend(oparg_T *oap)
static inline void pbyte(pos_T lp, int c)
{
assert(c <= UCHAR_MAX);
- *(ml_get_buf(curbuf, lp.lnum, true) + lp.col) = (char_u)c;
+ *(ml_get_buf(curbuf, lp.lnum, true) + lp.col) = (char)c;
if (!curbuf_splice_pending) {
extmark_splice_cols(curbuf, (int)lp.lnum - 1, lp.col, 1, 1, kExtmarkUndo);
}
@@ -1883,9 +2111,7 @@ static int op_replace(oparg_T *oap, int c)
return FAIL;
}
- /*
- * block mode replace
- */
+ // block mode replace
if (oap->motion_type == kMTBlockWise) {
bd.is_MAX = (curwin->w_curswant == MAXCOL);
for (; curwin->w_cursor.lnum <= oap->end.lnum; curwin->w_cursor.lnum++) {
@@ -1936,7 +2162,7 @@ static int op_replace(oparg_T *oap, int c)
num_chars = numc;
numc *= utf_char2len(c);
- oldp = get_cursor_line_ptr();
+ oldp = (char_u *)get_cursor_line_ptr();
oldlen = (int)STRLEN(oldp);
size_t newp_size = (size_t)bd.textcol + (size_t)bd.startspaces;
@@ -2000,9 +2226,9 @@ static int op_replace(oparg_T *oap, int c)
if (oap->motion_type == kMTLineWise) {
oap->start.col = 0;
curwin->w_cursor.col = 0;
- oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ 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));
@@ -2014,7 +2240,7 @@ static int op_replace(oparg_T *oap, int c)
n = gchar_cursor();
if (n != NUL) {
int new_byte_len = utf_char2len(c);
- int old_byte_len = utfc_ptr2len((char *)get_cursor_pos_ptr());
+ int old_byte_len = utfc_ptr2len(get_cursor_pos_ptr());
if (new_byte_len > 1 || old_byte_len > 1) {
// This is slow, but it handles replacing a single-byte
@@ -2090,7 +2316,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) {
@@ -2114,9 +2340,9 @@ void op_tilde(oparg_T *oap)
if (oap->motion_type == kMTLineWise) {
oap->start.col = 0;
pos.col = 0;
- oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+ 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));
@@ -2143,7 +2369,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) {
@@ -2165,7 +2391,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
{
@@ -2235,7 +2461,7 @@ bool swapchar(int op_type, pos_T *pos)
curwin->w_cursor = *pos;
// don't use del_char(), it also removes composing chars
- del_bytes(utf_ptr2len((char *)get_cursor_pos_ptr()), false, false);
+ del_bytes(utf_ptr2len(get_cursor_pos_ptr()), false, false);
ins_char(nc);
curwin->w_cursor = sp;
} else {
@@ -2250,7 +2476,7 @@ bool swapchar(int op_type, pos_T *pos)
void op_insert(oparg_T *oap, long count1)
{
long ins_len, pre_textlen = 0;
- char_u *firstline, *ins_text;
+ char *firstline, *ins_text;
colnr_T ind_pre_col = 0, ind_post_col;
int ind_pre_vcol = 0, ind_post_vcol = 0;
struct block_def bd;
@@ -2262,7 +2488,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
@@ -2282,7 +2508,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;
}
@@ -2303,10 +2529,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
@@ -2412,17 +2638,15 @@ 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;
bd.textlen = bd2.textlen;
}
- /*
- * Subsequent calls to ml_get() flush the firstline data - take a
- * copy of the required string.
- */
+ // Subsequent calls to ml_get() flush the firstline data - take a
+ // copy of the required string.
firstline = ml_get(oap->start.lnum);
const size_t len = STRLEN(firstline);
colnr_T add = bd.textcol;
@@ -2448,10 +2672,10 @@ void op_insert(oparg_T *oap, long count1)
}
ins_len = (long)STRLEN(firstline) - pre_textlen - offset;
if (pre_textlen >= 0 && ins_len > 0) {
- ins_text = vim_strnsave(firstline, (size_t)ins_len);
+ ins_text = xstrnsave(firstline, (size_t)ins_len);
// block handled here
if (u_save(oap->start.lnum, (linenr_T)(oap->end.lnum + 1)) == OK) {
- block_insert(oap, ins_text, (oap->op_type == OP_INSERT), &bd);
+ block_insert(oap, (char_u *)ins_text, (oap->op_type == OP_INSERT), &bd);
}
curwin->w_cursor.col = oap->start.col;
@@ -2463,7 +2687,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;
@@ -2489,10 +2713,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)
@@ -2508,9 +2732,9 @@ int op_change(oparg_T *oap)
|| gchar_cursor() == NUL)) {
coladvance_force(getviscol());
}
- firstline = ml_get(oap->start.lnum);
+ firstline = (char_u *)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;
}
@@ -2518,20 +2742,18 @@ 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
- * block.
- * Don't repeat the insert when Insert mode ended with CTRL-C.
- */
+ // In Visual block mode, handle copying the new text to all lines of the
+ // block.
+ // Don't repeat the insert when Insert mode ended with CTRL-C.
if (oap->motion_type == kMTBlockWise
&& oap->start.lnum != oap->end.lnum && !got_int) {
// Auto-indenting may have changed the indent. If the cursor was past
// the indent, exclude that indent change from the inserted text.
- firstline = ml_get(oap->start.lnum);
+ firstline = (char_u *)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);
@@ -2557,7 +2779,7 @@ int op_change(oparg_T *oap)
} else {
vpos.coladd = 0;
}
- oldp = ml_get(linenr);
+ oldp = (char_u *)ml_get(linenr);
newp = xmalloc(STRLEN(oldp) + (size_t)vpos.coladd
+ (size_t)ins_len + 1);
// copy up to block start
@@ -2584,13 +2806,22 @@ int op_change(oparg_T *oap)
return retval;
}
+
+/*
+ * set all the yank registers to empty (called from main())
+ */
+void init_yank(void)
+{
+ init_yankmap(&y_regs.inner);
+}
+
#if defined(EXITFREE)
void clear_registers(void)
{
int i;
for (i = 0; i < NUM_REGISTERS; i++) {
- free_register(&y_regs[i]);
+ free_register(get_global_reg(i));
}
}
@@ -2634,6 +2865,14 @@ bool op_yank(oparg_T *oap, bool message)
yankreg_T *reg = get_yank_register(oap->regname, YREG_YANK);
op_yank_reg(oap, message, reg, is_append_register(oap->regname));
+
+ if (get_userreg(oap->regname) != -1) {
+ if (eval_yank_userreg(curbuf->b_p_urf, oap->regname, reg) == -1) {
+ beep_flush();
+ return false;
+ }
+ }
+
set_clipboard(oap->regname, reg);
do_autocmd_textyankpost(oap, reg);
@@ -2701,14 +2940,14 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
break;
case kMTLineWise:
- reg->y_array[y_idx] = (char *)vim_strsave(ml_get(lnum));
+ reg->y_array[y_idx] = xstrdup(ml_get(lnum));
break;
case kMTCharWise: {
colnr_T startcol = 0, endcol = MAXCOL;
int is_oneChar = false;
colnr_T cs, ce;
- p = ml_get(lnum);
+ p = (char_u *)ml_get(lnum);
bd.startspaces = 0;
bd.endspaces = 0;
@@ -2717,8 +2956,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
if (virtual_op) {
getvcol(curwin, &oap->start, &cs, NULL, &ce);
if (ce != cs && oap->start.coladd > 0) {
- /* Part of a tab selected -- but don't
- * double-count it. */
+ // Part of a tab selected -- but don't double-count it.
bd.startspaces = (ce - cs + 1)
- oap->start.coladd;
startcol++;
@@ -2734,7 +2972,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
// Don't add space for double-wide
// char; endcol will be on last byte
// of multi-byte char.
- && utf_head_off(p, p + endcol) == 0)) {
+ && utf_head_off((char *)p, (char *)p + endcol) == 0)) {
if (oap->start.lnum == oap->end.lnum
&& oap->start.col == oap->end.col) {
// Special case: inside a single char
@@ -2786,8 +3024,8 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
// the new block, unless being Vi compatible.
if (curr->y_type == kMTCharWise
&& vim_strchr(p_cpo, CPO_REGAPPEND) == NULL) {
- pnew = xmalloc(STRLEN(curr->y_array[curr->y_size - 1])
- + STRLEN(reg->y_array[0]) + 1);
+ pnew = xmalloc(strlen(curr->y_array[curr->y_size - 1])
+ + strlen(reg->y_array[0]) + 1);
STRCPY(pnew, curr->y_array[--j]);
STRCAT(pnew, reg->y_array[0]);
xfree(curr->y_array[j]);
@@ -2815,7 +3053,11 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
if (oap->regname == NUL) {
*namebuf = NUL;
} else {
- vim_snprintf(namebuf, sizeof(namebuf), _(" into \"%c"), oap->regname);
+ char buf[5];
+ int len = (*utf_char2len) (oap->regname);
+ utf_char2bytes(oap->regname, buf);
+ buf[len] = 0;
+ vim_snprintf(namebuf, sizeof(namebuf), _(" into \"%s"), buf);
}
// redisplay now, so message is not deleted
@@ -2867,7 +3109,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx,
int s = bd->textlen + bd->endspaces;
while (s > 0 && ascii_iswhite(*(bd->textstart + s - 1))) {
- s = s - utf_head_off(bd->textstart, bd->textstart + s - 1) - 1;
+ s = s - utf_head_off((char *)bd->textstart, (char *)bd->textstart + s - 1) - 1;
pnew--;
}
}
@@ -2882,6 +3124,7 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
FUNC_ATTR_NONNULL_ALL
{
static bool recursive = false;
+ int len;
if (recursive || !has_event(EVENT_TEXTYANKPOST)) {
// No autocommand was defined, or we yanked from this autocommand.
@@ -2903,13 +3146,15 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
(void)tv_dict_add_list(dict, S_LEN("regcontents"), list);
// Register type.
- char buf[NUMBUFLEN + 2];
+ char buf[NUMBUFLEN + 6];
format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf));
(void)tv_dict_add_str(dict, S_LEN("regtype"), buf);
// Name of requested register, or empty string for unnamed operation.
- buf[0] = (char)oap->regname;
- buf[1] = NUL;
+ len = (*utf_char2len)(oap->regname);
+ buf[len] = 0;
+ utf_char2bytes(oap->regname, buf);
+ recursive = true;
(void)tv_dict_add_str(dict, S_LEN("regname"), buf);
// Motion type: inclusive or exclusive.
@@ -2944,9 +3189,9 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
/// @param dir BACKWARD for 'P', FORWARD for 'p'
void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
{
- char_u *ptr;
- char_u *newp;
- char_u *oldp;
+ char *ptr;
+ char *newp;
+ char *oldp;
int yanklen;
size_t totlen = 0; // init for gcc
linenr_T lnum = 0;
@@ -2983,10 +3228,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
curbuf->b_op_start = curwin->w_cursor; // default for '[ mark
curbuf->b_op_end = curwin->w_cursor; // default for '] mark
- /*
- * Using inserted text works differently, because the register includes
- * special characters (newlines, etc.).
- */
+ // Using inserted text works differently, because the register includes
+ // special characters (newlines, etc.).
if (regname == '.' && !reg) {
bool non_linewise_vis = (VIsual_active && VIsual_mode != 'V');
@@ -3038,7 +3281,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// STRLEN(ml_get(curwin->w_cursor.lnum)). With 'virtualedit' and the
// cursor past the end of the line, curwin->w_cursor.coladd is
// incremented instead of curwin->w_cursor.col.
- char_u *cursor_pos = get_cursor_pos_ptr();
+ char_u *cursor_pos = (char_u *)get_cursor_pos_ptr();
bool one_past_line = (*cursor_pos == NUL);
bool eol = false;
if (!one_past_line) {
@@ -3066,10 +3309,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
return;
}
- /*
- * For special registers '%' (file name), '#' (alternate file name) and
- * ':' (last command line), etc. we have to create a fake yank register.
- */
+ // For special registers '%' (file name), '#' (alternate file name) and
+ // ':' (last command line), etc. we have to create a fake yank register.
if (!reg && get_spec_reg(regname, &insert_string, &allocated, true)) {
if (insert_string == NULL) {
return;
@@ -3087,18 +3328,18 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (insert_string != NULL) {
y_type = kMTCharWise;
if (regname == '=') {
- /* For the = register we need to split the string at NL
- * characters.
- * Loop twice: count the number of lines and save them. */
+ // For the = register we need to split the string at NL
+ // characters.
+ // Loop twice: count the number of lines and save them.
for (;;) {
y_size = 0;
- ptr = (char_u *)insert_string;
+ ptr = insert_string;
while (ptr != NULL) {
if (y_array != NULL) {
- y_array[y_size] = (char *)ptr;
+ y_array[y_size] = ptr;
}
y_size++;
- ptr = (char_u *)vim_strchr((char *)ptr, '\n');
+ ptr = vim_strchr(ptr, '\n');
if (ptr != NULL) {
if (y_array != NULL) {
*ptr = NUL;
@@ -3146,12 +3387,12 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (u_save_cursor() == FAIL) {
goto end;
}
- char_u *p = get_cursor_pos_ptr();
+ char *p = get_cursor_pos_ptr();
if (dir == FORWARD && *p != NUL) {
MB_PTR_ADV(p);
}
- ptr = vim_strsave(p);
- ml_append(curwin->w_cursor.lnum, (char *)ptr, (colnr_T)0, false);
+ ptr = xstrdup(p);
+ ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, false);
xfree(ptr);
oldp = get_cursor_line_ptr();
@@ -3159,8 +3400,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (dir == FORWARD && *p != NUL) {
MB_PTR_ADV(p);
}
- ptr = vim_strnsave(oldp, (size_t)(p - oldp));
- ml_replace(curwin->w_cursor.lnum, (char *)ptr, false);
+ ptr = xstrnsave(oldp, (size_t)(p - oldp));
+ ml_replace(curwin->w_cursor.lnum, ptr, false);
nr_lines++;
dir = FORWARD;
}
@@ -3242,9 +3483,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
lnum = curwin->w_cursor.lnum;
col = curwin->w_cursor.col;
- /*
- * Block mode
- */
+ // Block mode
if (y_type == kMTBlockWise) {
int c = gchar_cursor();
colnr_T endcol2 = 0;
@@ -3257,7 +3496,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
// move to start of next multi-byte character
- curwin->w_cursor.col += utfc_ptr2len((char *)get_cursor_pos_ptr());
+ curwin->w_cursor.col += utfc_ptr2len(get_cursor_pos_ptr());
col++;
} else {
getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
@@ -3307,12 +3546,18 @@ 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 = cts.cts_ptr;
bd.textcol = (colnr_T)(ptr - oldp);
+ clear_chartabsize_arg(&cts);
shortline = (vcol < col) || (vcol == col && !*ptr);
@@ -3321,13 +3566,13 @@ 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) {
- /* Only a Tab can be split into spaces. Other
- * characters will have to be moved to after the
- * block, causing misalignment. */
+ // Only a Tab can be split into spaces. Other
+ // characters will have to be moved to after the
+ // block, causing misalignment.
delcount = 0;
bd.endspaces = 0;
}
@@ -3339,9 +3584,13 @@ 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, y_array[i], 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;
}
@@ -3355,9 +3604,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
break;
}
- totlen = (size_t)(count * (yanklen + spaces)
- + bd.startspaces + bd.endspaces);
- newp = (char_u *)xmalloc(totlen + oldlen + 1);
+ totlen = (size_t)(count * (yanklen + spaces) + bd.startspaces + bd.endspaces);
+ newp = xmalloc(totlen + oldlen + 1);
// copy part up to cursor to new line
ptr = newp;
@@ -3390,11 +3638,11 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
int columns = (int)oldlen - bd.textcol - delcount + 1;
assert(columns >= 0);
memmove(ptr, oldp + bd.textcol + delcount, (size_t)columns);
- ml_replace(curwin->w_cursor.lnum, (char *)newp, false);
+ ml_replace(curwin->w_cursor.lnum, newp, false);
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;
}
@@ -3431,7 +3679,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// if type is kMTCharWise, FORWARD is the same as BACKWARD on the next
// char
if (dir == FORWARD && gchar_cursor() != NUL) {
- int bytelen = utfc_ptr2len((char *)get_cursor_pos_ptr());
+ int bytelen = utfc_ptr2len(get_cursor_pos_ptr());
// put it on the next of the multi-byte character.
col += bytelen;
@@ -3497,7 +3745,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
lnum++;
continue;
}
- newp = (char_u *)xmalloc(totlen + oldlen + 1);
+ newp = xmalloc(totlen + oldlen + 1);
memmove(newp, oldp, (size_t)col);
ptr = newp + col;
for (i = 0; i < (size_t)count; i++) {
@@ -3505,7 +3753,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
ptr += yanklen;
}
STRMOVE(ptr, oldp + col);
- ml_replace(lnum, (char *)newp, false);
+ ml_replace(lnum, newp, false);
// compute the byte offset for the last character
first_byte_off = utf_head_off(newp, ptr - 1);
@@ -3554,21 +3802,21 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
lnum = new_cursor.lnum;
ptr = ml_get(lnum) + col;
totlen = STRLEN(y_array[y_size - 1]);
- newp = (char_u *)xmalloc((size_t)(STRLEN(ptr) + totlen + 1));
+ newp = xmalloc((size_t)(STRLEN(ptr) + totlen + 1));
STRCPY(newp, y_array[y_size - 1]);
STRCAT(newp, ptr);
// insert second line
- ml_append(lnum, (char *)newp, (colnr_T)0, false);
+ ml_append(lnum, newp, (colnr_T)0, false);
new_lnum++;
xfree(newp);
oldp = ml_get(lnum);
- newp = (char_u *)xmalloc((size_t)col + (size_t)yanklen + 1);
+ newp = xmalloc((size_t)col + (size_t)yanklen + 1);
// copy first part of line
memmove(newp, oldp, (size_t)col);
// append to first line
memmove(newp + col, y_array[0], (size_t)yanklen + 1);
- ml_replace(lnum, (char *)newp, false);
+ ml_replace(lnum, newp, false);
curwin->w_cursor.lnum = lnum;
i = 1;
@@ -3666,8 +3914,8 @@ error:
if (col > 1) {
curbuf->b_op_end.col = col - 1;
if (len > 0) {
- curbuf->b_op_end.col -= utf_head_off((char_u *)y_array[y_size - 1],
- (char_u *)y_array[y_size - 1] + len - 1);
+ curbuf->b_op_end.col -= utf_head_off(y_array[y_size - 1],
+ y_array[y_size - 1] + len - 1);
}
} else {
curbuf->b_op_end.col = 0;
@@ -3698,7 +3946,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
@@ -3708,7 +3956,7 @@ error:
}
msgmore(nr_lines);
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
end:
if (cmdmod.cmod_flags & CMOD_LOCKMARKS) {
@@ -3722,7 +3970,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();
@@ -3751,7 +3999,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)
@@ -3780,7 +4028,7 @@ int get_register_name(int num)
/// @return the index of the register "" points to.
int get_unname_register(void)
{
- return y_previous == NULL ? -1 : (int)(y_previous - &y_regs[0]);
+ return yankmap_find(&y_regs.inner, y_previous);
}
/// ":dis" and ":registers": Display the contents of the yank registers.
@@ -3819,10 +4067,10 @@ void ex_display(exarg_T *eap)
if (y_previous != NULL) {
yb = y_previous;
} else {
- yb = &(y_regs[0]);
+ yb = get_global_reg(0);
}
} else {
- yb = &(y_regs[i]);
+ yb = get_global_reg(i);
}
get_clipboard(name, &yb, true);
@@ -3837,7 +4085,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) {
@@ -3858,14 +4106,13 @@ 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;
}
}
if (n > 1 && yb->y_type == kMTLineWise) {
msg_puts_attr("^J", attr);
}
- ui_flush(); // show one line at a time
}
os_breakcheck();
}
@@ -3874,9 +4121,9 @@ 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);
+ dis_msg((char *)p, true);
}
// display last command line
@@ -3889,9 +4136,9 @@ void ex_display(exarg_T *eap)
// 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);
+ dis_msg(curbuf->b_fname, false);
}
// display alternate file name
@@ -3899,25 +4146,25 @@ 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);
+ dis_msg(fname, false);
}
}
// 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);
+ dis_msg((char *)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);
+ dis_msg((char *)expr_line, false);
}
}
@@ -3925,7 +4172,7 @@ void ex_display(exarg_T *eap)
/// truncate at end of screen line
///
/// @param skip_esc if true, ignore trailing ESC
-static void dis_msg(const char_u *p, bool skip_esc)
+static void dis_msg(const char *p, bool skip_esc)
FUNC_ATTR_NONNULL_ALL
{
int n;
@@ -3934,8 +4181,8 @@ static void dis_msg(const char_u *p, bool skip_esc)
n = Columns - 6;
while (*p != NUL
&& !(*p == ESC && skip_esc && *(p + 1) == NUL)
- && (n -= ptr2cells((char *)p)) >= 0) {
- if ((l = utfc_ptr2len((char *)p)) > 1) {
+ && (n -= ptr2cells(p)) >= 0) {
+ if ((l = utfc_ptr2len(p)) > 1) {
msg_outtrans_len(p, l);
p += l;
} else {
@@ -3956,11 +4203,11 @@ static void dis_msg(const char_u *p, bool skip_esc)
/// @param include_space - whether to skip space following the comment leader
/// @param[out] is_comment - whether the current line ends with an unclosed
/// comment.
-char_u *skip_comment(char_u *line, bool process, bool include_space, bool *is_comment)
+char *skip_comment(char *line, bool process, bool include_space, bool *is_comment)
{
char *comment_flags = NULL;
int lead_len;
- int leader_offset = get_last_leader_offset((char *)line, &comment_flags);
+ int leader_offset = get_last_leader_offset(line, &comment_flags);
*is_comment = false;
if (leader_offset != -1) {
@@ -3982,7 +4229,7 @@ char_u *skip_comment(char_u *line, bool process, bool include_space, bool *is_co
return line;
}
- lead_len = get_leader_len((char *)line, &comment_flags, false, include_space);
+ lead_len = get_leader_len(line, &comment_flags, false, include_space);
if (lead_len == 0) {
return line;
@@ -4011,8 +4258,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.
@@ -4020,11 +4267,11 @@ char_u *skip_comment(char_u *line, bool process, bool include_space, bool *is_co
/// @return FAIL for failure, OK otherwise
int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions, bool setmark)
{
- char_u *curr = NULL;
- char_u *curr_start = NULL;
- char_u *cend;
- char_u *newp;
- char_u *spaces; // number of spaces inserted before a line
+ char *curr = NULL;
+ char *curr_start = NULL;
+ char *cend;
+ char *newp;
+ char *spaces; // number of spaces inserted before a line
int endcurr1 = NUL;
int endcurr2 = NUL;
int currsize = 0; // size of the current line
@@ -4033,7 +4280,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);
@@ -4053,7 +4300,8 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
// Don't move anything, just compute the final line length
// and setup the array of space strings lengths
for (t = 0; t < (linenr_T)count; t++) {
- curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t));
+ curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t));
+ curr = curr_start;
if (t == 0 && setmark && (cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
// Set the '[ mark.
curwin->w_buffer->b_op_start.lnum = curwin->w_cursor.lnum;
@@ -4063,8 +4311,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
// We don't want to remove the comment leader if the
// previous line is not a comment.
if (t > 0 && prev_was_comment) {
- char_u *new_curr = skip_comment(curr, true, insert_space,
- &prev_was_comment);
+ char *new_curr = skip_comment(curr, true, insert_space, &prev_was_comment);
comments[t] = (int)(new_curr - curr);
curr = new_curr;
} else {
@@ -4073,26 +4320,26 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
}
if (insert_space && t > 0) {
- curr = (char_u *)skipwhite((char *)curr);
+ curr = skipwhite(curr);
if (*curr != NUL
&& *curr != ')'
&& sumsize != 0
&& endcurr1 != TAB
&& (!has_format_option(FO_MBYTE_JOIN)
- || (utf_ptr2char((char *)curr) < 0x100 && endcurr1 < 0x100))
+ || (utf_ptr2char(curr) < 0x100 && endcurr1 < 0x100))
&& (!has_format_option(FO_MBYTE_JOIN2)
- || (utf_ptr2char((char *)curr) < 0x100 && !utf_eat_space(endcurr1))
+ || (utf_ptr2char(curr) < 0x100 && !utf_eat_space(endcurr1))
|| (endcurr1 < 0x100
- && !utf_eat_space(utf_ptr2char((char *)curr))))) {
+ && !utf_eat_space(utf_ptr2char(curr))))) {
// don't add a space if the line is ending in a space
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]++;
}
}
}
@@ -4110,10 +4357,10 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
if (insert_space && currsize > 0) {
cend = curr + currsize;
MB_PTR_BACK(curr, cend);
- endcurr1 = utf_ptr2char((char *)cend);
+ endcurr1 = utf_ptr2char(cend);
if (cend > curr) {
MB_PTR_BACK(curr, cend);
- endcurr2 = utf_ptr2char((char *)cend);
+ endcurr2 = utf_ptr2char(cend);
}
}
line_breakcheck();
@@ -4127,17 +4374,15 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
col = sumsize - currsize - spaces[count - 1];
// allocate the space for the new line
- newp = (char_u *)xmalloc((size_t)sumsize + 1);
+ newp = xmalloc((size_t)sumsize + 1);
cend = newp + sumsize;
*cend = 0;
- /*
- * Move affected lines to the new long one.
- *
- * Move marks from each deleted line to the joined line, adjusting the
- * column. This is not Vi compatible, but Vi deletes the marks, thus that
- * should not really be a problem.
- */
+ // Move affected lines to the new long one.
+ //
+ // Move marks from each deleted line to the joined line, adjusting the
+ // column. This is not Vi compatible, but Vi deletes the marks, thus that
+ // should not really be a problem.
curbuf_splice_pending++;
@@ -4163,17 +4408,18 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
break;
}
- curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1));
+ curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1));
+ curr = curr_start;
if (remove_comments) {
curr += comments[t - 1];
}
if (insert_space && t > 1) {
- curr = (char_u *)skipwhite((char *)curr);
+ curr = skipwhite(curr);
}
currsize = (int)STRLEN(curr);
}
- ml_replace(curwin->w_cursor.lnum, (char *)newp, false);
+ ml_replace(curwin->w_cursor.lnum, newp, false);
if (setmark && (cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) {
// Set the '] mark.
@@ -4186,11 +4432,9 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
changed_lines(curwin->w_cursor.lnum, currsize,
curwin->w_cursor.lnum + 1, 0L, true);
- /*
- * Delete following lines. To do this we move the cursor there
- * briefly, and then move it back. After del_lines() the cursor may
- * have moved up (last line deleted), so the current lnum is kept in t.
- */
+ // Delete following lines. To do this we move the cursor there
+ // briefly, and then move it back. After del_lines() the cursor may
+ // have moved up (last line deleted), so the current lnum is kept in t.
t = curwin->w_cursor.lnum;
curwin->w_cursor.lnum++;
del_lines((long)count - 1, false);
@@ -4198,17 +4442,15 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
curbuf_splice_pending--;
curbuf->deleted_bytes2 = 0;
- /*
- * Set the cursor column:
- * Vi compatible: use the column of the first join
- * vim: use the column of the last join
- */
+ // Set the cursor column:
+ // Vi compatible: use the column of the first join
+ // vim: use the column of the last join
curwin->w_cursor.col =
(vim_strchr(p_cpo, CPO_JOINCOL) != NULL ? currsize : col);
check_cursor_col();
curwin->w_cursor.coladd = 0;
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
theend:
xfree(spaces);
@@ -4218,532 +4460,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:
@@ -4758,11 +4474,11 @@ int paragraph_start(linenr_T lnum)
static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool is_del)
{
int incr = 0;
- char_u *pend;
- char_u *pstart;
- char_u *line;
- char_u *prev_pstart;
- char_u *prev_pend;
+ char *pend;
+ char *pstart;
+ char *line;
+ char *prev_pstart;
+ char *prev_pend;
const int lbr_saved = curwin->w_p_lbr;
// Avoid a problem with unwanted linebreaks in block mode.
@@ -4780,22 +4496,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 = cts.cts_ptr;
+ MB_PTR_ADV(cts.cts_ptr);
}
+ bdp->start_vcol = cts.cts_vcol;
+ pstart = 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;
@@ -4831,13 +4553,18 @@ 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 = cts.cts_ptr;
+ incr = lbr_chartabsize_adv(&cts);
+ cts.cts_vcol += incr;
}
+ bdp->end_vcol = cts.cts_vcol;
+ pend = cts.cts_ptr;
+ clear_chartabsize_arg(&cts);
+
if (bdp->end_vcol <= oap->end_vcol
&& (!is_del
|| oap->op_type == OP_APPEND
@@ -4868,7 +4595,7 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
bdp->textlen = (int)(pend - pstart);
}
bdp->textcol = (colnr_T)(pstart - line);
- bdp->textstart = pstart;
+ bdp->textstart = (char_u *)pstart;
curwin->w_p_lbr = lbr_saved;
}
@@ -4962,7 +4689,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
@@ -5010,12 +4737,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;
@@ -5023,7 +4750,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
}
curwin->w_cursor = *pos;
- ptr = ml_get(pos->lnum);
+ ptr = (char_u *)ml_get(pos->lnum);
col = pos->col;
if (*ptr == NUL || col + !!save_coladd >= (int)STRLEN(ptr)) {
@@ -5035,14 +4762,14 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
if (do_bin) {
while (col > 0 && ascii_isbdigit(ptr[col])) {
col--;
- col -= utf_head_off(ptr, ptr + col);
+ col -= utf_head_off((char *)ptr, (char *)ptr + col);
}
}
if (do_hex) {
while (col > 0 && ascii_isxdigit(ptr[col])) {
col--;
- col -= utf_head_off(ptr, ptr + col);
+ col -= utf_head_off((char *)ptr, (char *)ptr + col);
}
}
if (do_bin
@@ -5050,7 +4777,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
&& !((col > 0
&& (ptr[col] == 'X' || ptr[col] == 'x')
&& ptr[col - 1] == '0'
- && !utf_head_off(ptr, ptr + col - 1)
+ && !utf_head_off((char *)ptr, (char *)ptr + col - 1)
&& ascii_isxdigit(ptr[col + 1])))) {
// In case of binary/hexadecimal pattern overlap match, rescan
@@ -5058,7 +4785,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
while (col > 0 && ascii_isdigit(ptr[col])) {
col--;
- col -= utf_head_off(ptr, ptr + col);
+ col -= utf_head_off((char *)ptr, (char *)ptr + col);
}
}
@@ -5066,17 +4793,17 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
&& col > 0
&& (ptr[col] == 'X' || ptr[col] == 'x')
&& ptr[col - 1] == '0'
- && !utf_head_off(ptr, ptr + col - 1)
+ && !utf_head_off((char *)ptr, (char *)ptr + col - 1)
&& ascii_isxdigit(ptr[col + 1]))
|| (do_bin
&& col > 0
&& (ptr[col] == 'B' || ptr[col] == 'b')
&& ptr[col - 1] == '0'
- && !utf_head_off(ptr, ptr + col - 1)
+ && !utf_head_off((char *)ptr, (char *)ptr + col - 1)
&& ascii_isbdigit(ptr[col + 1]))) {
// Found hexadecimal or binary number, move to its start.
col--;
- col -= utf_head_off(ptr, ptr + col);
+ col -= utf_head_off((char *)ptr, (char *)ptr + col);
} else {
// Search forward and then backward to find the start of number.
col = pos->col;
@@ -5109,7 +4836,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
}
if (col > pos->col && ptr[col - 1] == '-'
- && !utf_head_off(ptr, ptr + col - 1)
+ && !utf_head_off((char *)ptr, (char *)ptr + col - 1)
&& !do_unsigned) {
negative = true;
was_positive = false;
@@ -5155,7 +4882,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
curwin->w_cursor.col = col;
} else {
if (col > 0 && ptr[col - 1] == '-'
- && !utf_head_off(ptr, ptr + col - 1)
+ && !utf_head_off((char *)ptr, (char *)ptr + col - 1)
&& !visual
&& !do_unsigned) {
// negative number
@@ -5170,7 +4897,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
: length);
}
- vim_str2nr(ptr + col, &pre, &length,
+ vim_str2nr((char *)ptr + col, &pre, &length,
0 + (do_bin ? STR2NR_BIN : 0)
+ (do_oct ? STR2NR_OCT : 0)
+ (do_hex ? STR2NR_HEX : 0),
@@ -5314,7 +5041,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--;
@@ -5412,13 +5139,13 @@ void format_reg_type(MotionType reg_type, colnr_T reg_width, char *buf, size_t b
/// Otherwise just return `s`.
///
/// @return a void * for use in get_reg_contents().
-static void *get_reg_wrap_one_line(char_u *s, int flags)
+static void *get_reg_wrap_one_line(char *s, int flags)
{
if (!(flags & kGRegList)) {
return s;
}
list_T *const list = tv_list_alloc(1);
- tv_list_append_allocated_string(list, (char *)s);
+ tv_list_append_allocated_string(list, s);
return list;
}
@@ -5460,9 +5187,9 @@ void *get_reg_contents(int regname, int flags)
return NULL;
}
if (allocated) {
- return get_reg_wrap_one_line((char_u *)retval, flags);
+ return get_reg_wrap_one_line(retval, flags);
}
- return get_reg_wrap_one_line(vim_strsave((char_u *)retval), flags);
+ return get_reg_wrap_one_line(xstrdup(retval), flags);
}
yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
@@ -5479,16 +5206,12 @@ void *get_reg_contents(int regname, int flags)
return list;
}
- /*
- * Compute length of resulting string.
- */
+ // Compute length of resulting string.
size_t len = 0;
for (size_t i = 0; i < reg->y_size; i++) {
len += STRLEN(reg->y_array[i]);
- /*
- * Insert a newline between lines and after last line if
- * y_type is kMTLineWise.
- */
+ // Insert a newline between lines and after last line if
+ // y_type is kMTLineWise.
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
len++;
}
@@ -5496,18 +5219,14 @@ void *get_reg_contents(int regname, int flags)
retval = xmalloc(len + 1);
- /*
- * Copy the lines of the yank register into the string.
- */
+ // Copy the lines of the yank register into the string.
len = 0;
for (size_t i = 0; i < reg->y_size; i++) {
STRCPY(retval + len, reg->y_array[i]);
len += STRLEN(retval + len);
- /*
- * Insert a NL between lines and after the last line if y_type is
- * kMTLineWise.
- */
+ // Insert a NL between lines and after the last line if y_type is
+ // kMTLineWise.
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
retval[len++] = '\n';
}
@@ -5536,6 +5255,10 @@ static yankreg_T *init_write_reg(int name, yankreg_T **old_y_previous, bool must
static void finish_write_reg(int name, yankreg_T *reg, yankreg_T *old_y_previous)
{
+ if (get_userreg(name) != -1) {
+ eval_yank_userreg(curbuf->b_p_urf, name, reg);
+ }
+
// Send text of clipboard register to the clipboard.
set_clipboard(name, reg);
@@ -5548,7 +5271,7 @@ static void finish_write_reg(int name, yankreg_T *reg, yankreg_T *old_y_previous
/// store `str` in register `name`
///
/// @see write_reg_contents_ex
-void write_reg_contents(int name, const char_u *str, ssize_t len, int must_append)
+void write_reg_contents(int name, const char *str, ssize_t len, int must_append)
{
write_reg_contents_ex(name, str, len, must_append, kMTUnknown, 0L);
}
@@ -5557,9 +5280,9 @@ void write_reg_contents_lst(int name, char **strings, bool must_append, MotionTy
colnr_T block_len)
{
if (name == '/' || name == '=') {
- char_u *s = (char_u *)strings[0];
+ char *s = strings[0];
if (strings[0] == NULL) {
- s = (char_u *)"";
+ s = "";
} else if (strings[1] != NULL) {
emsg(_("E883: search pattern and expression register may not "
"contain two or more lines"));
@@ -5579,7 +5302,7 @@ void write_reg_contents_lst(int name, char **strings, bool must_append, MotionTy
return;
}
- str_to_reg(reg, yank_type, (char *)strings, STRLEN((char_u *)strings),
+ str_to_reg(reg, yank_type, (char *)strings, STRLEN(strings),
block_len, true);
finish_write_reg(name, reg, old_y_previous);
}
@@ -5602,7 +5325,7 @@ void write_reg_contents_lst(int name, char **strings, bool must_append, MotionTy
/// is an uppercase letter.
/// @param yank_type The motion type (kMTUnknown to auto detect)
/// @param block_len width of visual block
-void write_reg_contents_ex(int name, const char_u *str, ssize_t len, bool must_append,
+void write_reg_contents_ex(int name, const char *str, ssize_t len, bool must_append,
MotionType yank_type, colnr_T block_len)
{
if (len < 0) {
@@ -5611,7 +5334,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((char_u *)str, RE_SEARCH, true, true);
return;
}
@@ -5619,14 +5342,14 @@ void write_reg_contents_ex(int name, const char_u *str, ssize_t len, bool must_a
buf_T *buf;
if (ascii_isdigit(*str)) {
- int num = atoi((char *)str);
+ int num = atoi(str);
buf = buflist_findnr(num);
if (buf == NULL) {
semsg(_(e_nobufnr), (int64_t)num);
}
} else {
- buf = buflist_findnr(buflist_findpat((char *)str, (char *)str + STRLEN(str),
+ buf = buflist_findnr(buflist_findpat(str, str + STRLEN(str),
true, false, false));
}
if (buf == NULL) {
@@ -5667,7 +5390,7 @@ void write_reg_contents_ex(int name, const char_u *str, ssize_t len, bool must_a
if (!(reg = init_write_reg(name, &old_y_previous, must_append))) {
return;
}
- str_to_reg(reg, yank_type, (char *)str, (size_t)len, block_len, false);
+ str_to_reg(reg, yank_type, str, (size_t)len, block_len, false);
finish_write_reg(name, reg, old_y_previous);
}
@@ -5701,18 +5424,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
}
}
@@ -5733,7 +5456,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) {
@@ -5883,12 +5606,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;
@@ -5896,8 +5619,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) {
@@ -5913,7 +5635,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();
@@ -5938,7 +5660,7 @@ void cursor_pos_info(dict_T *dict)
len = (long)bd.textlen;
break;
case 'V':
- s = ml_get(lnum);
+ s = (char_u *)ml_get(lnum);
len = MAXCOL;
break;
case 'v': {
@@ -5947,7 +5669,7 @@ void cursor_pos_info(dict_T *dict)
colnr_T end_col = (lnum == max_pos.lnum)
? max_pos.col - start_col + 1 : MAXCOL;
- s = ml_get(lnum) + start_col;
+ s = (char_u *)ml_get(lnum) + start_col;
len = end_col;
}
break;
@@ -5968,14 +5690,14 @@ void cursor_pos_info(dict_T *dict)
word_count_cursor += word_count;
char_count_cursor += char_count;
byte_count_cursor = byte_count
- + line_count_info(ml_get(lnum), &word_count_cursor,
+ + line_count_info((char_u *)ml_get(lnum), &word_count_cursor,
&char_count_cursor,
(varnumber_T)curwin->w_cursor.col + 1,
eol_size);
}
}
// Add to the running totals
- byte_count += line_count_info(ml_get(lnum), &word_count, &char_count,
+ byte_count += line_count_info((char_u *)ml_get(lnum), &word_count, &char_count,
(varnumber_T)MAXCOL, eol_size);
}
@@ -6019,7 +5741,7 @@ void cursor_pos_info(dict_T *dict)
(int64_t)byte_count_cursor, (int64_t)byte_count);
}
} else {
- p = get_cursor_line_ptr();
+ p = (char_u *)get_cursor_line_ptr();
validate_virtcol();
col_print((char *)buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
(int)curwin->w_virtcol + 1);
@@ -6060,14 +5782,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;
}
}
@@ -6353,7 +6075,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) {
@@ -6363,7 +6085,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);
}
@@ -6596,7 +6318,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);
}
}
}
@@ -6628,7 +6350,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
@@ -6962,7 +6684,7 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
}
if (explicit_cb_reg) {
- target = &y_regs[*name == '*' ? STAR_REGISTER : PLUS_REGISTER];
+ target = get_global_reg(*name == '*' ? STAR_REGISTER : PLUS_REGISTER);
if (writing && (cb_flags & (*name == '*' ? CB_UNNAMED : CB_UNNAMEDPLUS))) {
clipboard_needs_update = false;
}
@@ -6979,10 +6701,10 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
if (cb_flags & CB_UNNAMEDPLUS) {
*name = (cb_flags & CB_UNNAMED && writing) ? '"': '+';
- target = &y_regs[PLUS_REGISTER];
+ target = get_global_reg(PLUS_REGISTER);
} else {
*name = '*';
- target = &y_regs[STAR_REGISTER];
+ target = get_global_reg(STAR_REGISTER);
}
goto end;
}
@@ -7298,11 +7020,11 @@ static inline bool reg_empty(const yankreg_T *const reg)
/// Iterate over global registers.
///
/// @see op_register_iter
-const void *op_global_reg_iter(const void *const iter, char *const name, yankreg_T *const reg,
- bool *is_unnamed)
+iter_register_T op_global_reg_iter(iter_register_T iter, char *const name,
+ yankreg_T *const reg, bool *is_unnamed)
FUNC_ATTR_NONNULL_ARG(2, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT
{
- return op_reg_iter(iter, y_regs, name, reg, is_unnamed);
+ return op_reg_iter(iter, &y_regs, name, reg, is_unnamed);
}
/// Iterate over registers `regs`.
@@ -7314,30 +7036,31 @@ const void *op_global_reg_iter(const void *const iter, char *const name, yankreg
///
/// @return Pointer that must be passed to next `op_register_iter` call or
/// NULL if iteration is over.
-const void *op_reg_iter(const void *const iter, const yankreg_T *const regs, char *const name,
- yankreg_T *const reg, bool *is_unnamed)
+iter_register_T op_reg_iter(iter_register_T iter, yank_registers_T *regs,
+ char *const name, yankreg_T *const reg,
+ bool *is_unnamed)
FUNC_ATTR_NONNULL_ARG(3, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT
{
*name = NUL;
- const yankreg_T *iter_reg = (iter == NULL
- ? &(regs[0])
- : (const yankreg_T *const)iter);
- while (iter_reg - &(regs[0]) < NUM_SAVED_REGISTERS && reg_empty(iter_reg)) {
- iter_reg++;
- }
- if (iter_reg - &(regs[0]) == NUM_SAVED_REGISTERS || reg_empty(iter_reg)) {
- return NULL;
- }
- int iter_off = (int)(iter_reg - &(regs[0]));
- *name = (char)get_register_name(iter_off);
- *reg = *iter_reg;
- *is_unnamed = (iter_reg == y_previous);
- while (++iter_reg - &(regs[0]) < NUM_SAVED_REGISTERS) {
- if (!reg_empty(iter_reg)) {
- return (void *)iter_reg;
+ int iter_idx = (int)(iter == ITER_REGISTER_NULL ? 0 : iter - 1);
+
+ while (iter_idx < NUM_SAVED_REGISTERS && reg_empty(get_reg(regs, iter_idx)))
+ ++iter_idx;
+
+ if (iter_idx >= NUM_SAVED_REGISTERS || reg_empty(get_reg(regs, iter_idx)))
+ return ITER_REGISTER_NULL;
+
+ *reg = *get_reg(regs, iter_idx);
+ *name = (char)get_register_name((int)iter_idx);
+ *is_unnamed = (get_reg(regs, iter_idx) == y_previous);
+
+ while (++iter_idx < NUM_SAVED_REGISTERS) {
+ if (!reg_empty(get_reg(regs, iter_idx))) {
+ return (iter_register_T)(iter_idx + 1);
}
}
- return NULL;
+
+ return ITER_REGISTER_NULL;
}
/// Get a number of non-empty registers
@@ -7345,8 +7068,8 @@ size_t op_reg_amount(void)
FUNC_ATTR_WARN_UNUSED_RESULT
{
size_t ret = 0;
- for (size_t i = 0; i < NUM_SAVED_REGISTERS; i++) {
- if (!reg_empty(y_regs + i)) {
+ for (int i = 0; i < NUM_SAVED_REGISTERS; i++) {
+ if (!reg_empty(get_global_reg(i))) {
ret++;
}
}
@@ -7366,11 +7089,11 @@ bool op_reg_set(const char name, const yankreg_T reg, bool is_unnamed)
if (i == -1) {
return false;
}
- free_register(&y_regs[i]);
- y_regs[i] = reg;
+ free_register(get_global_reg(i));
+ *get_global_reg(i) = reg;
if (is_unnamed) {
- y_previous = &y_regs[i];
+ y_previous = get_global_reg(i);
}
return true;
}
@@ -7386,7 +7109,7 @@ const yankreg_T *op_reg_get(const char name)
if (i == -1) {
return NULL;
}
- return &y_regs[i];
+ return get_global_reg(i);
}
/// Set the previous yank register
@@ -7401,7 +7124,7 @@ bool op_reg_set_previous(const char name)
return false;
}
- y_previous = &y_regs[i];
+ y_previous = get_global_reg(i);
return true;
}
diff --git a/src/nvim/ops.h b/src/nvim/ops.h
index 05893c9940..1e36afe6d0 100644
--- a/src/nvim/ops.h
+++ b/src/nvim/ops.h
@@ -22,22 +22,22 @@ typedef int (*Indenter)(void);
#define PUT_LINE_SPLIT 16 // split line for linewise register
#define PUT_LINE_FORWARD 32 // put linewise register below Visual sel.
#define PUT_BLOCK_INNER 64 // in block mode, do not add trailing spaces
+#define ITER_REGISTER_NULL 0
-/*
- * Registers:
- * 0 = register for latest (unnamed) yank
- * 1..9 = registers '1' to '9', for deletes
- * 10..35 = registers 'a' to 'z'
- * 36 = delete register '-'
- * 37 = selection register '*'
- * 38 = clipboard register '+'
- */
+// Registers:
+// 0 = register for latest (unnamed) yank
+// 1..9 = registers '1' to '9', for deletes
+// 10..35 = registers 'a' to 'z'
+// 36 = delete register '-'
+// 37 = selection register '*'
+// 38 = clipboard register '+'
#define DELETION_REGISTER 36
#define NUM_SAVED_REGISTERS 37
// The following registers should not be saved in ShaDa file:
#define STAR_REGISTER 37
#define PLUS_REGISTER 38
-#define NUM_REGISTERS 39
+#define USER_REGISTERS_START 39
+#define NUM_REGISTERS USER_REGISTERS_START
// Operator IDs; The order must correspond to opchars[] in ops.c!
#define OP_NOP 0 // no pending operation
@@ -88,6 +88,7 @@ typedef struct yankreg {
colnr_T y_width; ///< Register width (only valid for y_type == kBlockWise).
Timestamp timestamp; ///< Time when register was last modified.
dict_T *additional_data; ///< Additional data from ShaDa file.
+ int name;
} yankreg_T;
/// Modes for get_yank_register()
@@ -96,6 +97,8 @@ typedef enum {
YREG_YANK,
YREG_PUT,
} yreg_mode_t;
+/// Returns a reference to a user-defined register.
+int get_userreg(const int regname);
/// Convert register name into register index
///
@@ -118,10 +121,15 @@ static inline int op_reg_index(const int regname)
} else if (regname == '+') {
return PLUS_REGISTER;
} else {
- return -1;
+ return get_userreg(regname);
}
}
+struct yank_registers;
+typedef struct yank_registers yank_registers_T;
+
+typedef size_t iter_register_T;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ops.h.generated.h"
#endif
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 5c487a7c62..6636436f6e 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,14 +93,25 @@
#include "nvim/os/input.h"
#include "nvim/os/lang.h"
-/*
- * The options that are local to a window or buffer have "indir" set to one of
- * these values. Special values:
- * PV_NONE: global option.
- * PV_WIN is added: window-local option
- * PV_BUF is added: buffer-local option
- * PV_BOTH is added: global option which also has a local value.
- */
+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:
+// PV_NONE: global option.
+// PV_WIN is added: window-local option
+// PV_BUF is added: buffer-local option
+// PV_BOTH is added: global option which also has a local value.
#define PV_BOTH 0x1000
#define PV_WIN 0x2000
#define PV_BUF 0x4000
@@ -113,10 +126,8 @@ typedef enum {
PV_MAXVAL = 0xffff, // to avoid warnings for value out of range
} idopt_T;
-/*
- * Options local to a window have a value local to a buffer and global to all
- * buffers. Indicate this by setting "var" to VAR_WIN.
- */
+// Options local to a window have a value local to a buffer and global to all
+// buffers. Indicate this by setting "var" to VAR_WIN.
#define VAR_WIN ((char_u *)-1)
static char *p_term = NULL;
@@ -134,7 +145,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
@@ -145,18 +156,16 @@ typedef struct vimoption {
// buffer-local option: global value
idopt_T indir; // global option: PV_NONE;
// local option: indirect option index
- char_u *def_val; // default values for variable (neovim!!)
+ char *def_val; // default values for variable (neovim!!)
LastSet last_set; // script in which the option was last set
} vimoption_T;
-/*
- * options[] is initialized here.
- * The order of the options MUST be alphabetic for ":set all" and findoption().
- * All option names MUST start with a lowercase letter (for findoption()).
- * Exception: "t_" options are at the end.
- * The options with a NULL variable are 'hidden': a set command for them is
- * ignored and they are not printed.
- */
+// options[] is initialized here.
+// The order of the options MUST be alphabetic for ":set all" and findoption().
+// All option names MUST start with a lowercase letter (for findoption()).
+// Exception: "t_" options are at the end.
+// The options with a NULL variable are 'hidden': a set command for them is
+// ignored and they are not printed.
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "options.generated.h"
@@ -182,10 +191,8 @@ void set_init_1(bool clean_arg)
langmap_init();
- /*
- * Find default value for 'shell' option.
- * Don't use it if it is empty.
- */
+ // Find default value for 'shell' option.
+ // Don't use it if it is empty.
{
const char *shell = os_getenv("SHELL");
if (shell != NULL) {
@@ -200,10 +207,8 @@ void set_init_1(bool clean_arg)
}
}
- /*
- * Set the default for 'backupskip' to include environment variables for
- * temp files.
- */
+ // Set the default for 'backupskip' to include environment variables for
+ // temp files.
{
#ifdef UNIX
static char *(names[4]) = { "", "TMPDIR", "TEMP", "TMP" };
@@ -285,7 +290,7 @@ void set_init_1(bool clean_arg)
buf[j] = NUL;
opt_idx = findoption("cdpath");
if (opt_idx >= 0) {
- options[opt_idx].def_val = buf;
+ options[opt_idx].def_val = (char *)buf;
options[opt_idx].flags |= P_DEF_ALLOCED;
} else {
xfree(buf); // cannot happen
@@ -339,10 +344,8 @@ void set_init_1(bool clean_arg)
rtp = NULL; // ownership taken
}
- /*
- * Set all the options (except the terminal options) to their default
- * value. Also set the global value for local options.
- */
+ // Set all the options (except the terminal options) to their default
+ // value. Also set the global value for local options.
set_options_default(0);
curbuf->b_p_initialized = true;
@@ -365,15 +368,13 @@ void set_init_1(bool clean_arg)
// didset_options() because it only depends on 'encoding'.
init_spell_chartab();
- /*
- * Expand environment variables and things like "~" for the defaults.
- * If option_expand() returns non-NULL the variable is expanded. This can
- * only happen for non-indirect options.
- * Also set the default to the expanded value, so ":set" does not list
- * them.
- * Don't set the P_ALLOCED flag, because we don't want to free the
- * default.
- */
+ // Expand environment variables and things like "~" for the defaults.
+ // If option_expand() returns non-NULL the variable is expanded. This can
+ // only happen for non-indirect options.
+ // Also set the default to the expanded value, so ":set" does not list
+ // them.
+ // Don't set the P_ALLOCED flag, because we don't want to free the
+ // default.
for (opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
if (options[opt_idx].flags & P_NO_DEF_EXP) {
continue;
@@ -383,7 +384,7 @@ void set_init_1(bool clean_arg)
&& options[opt_idx].var != NULL) {
p = _(*(char **)options[opt_idx].var);
} else {
- p = (char *)option_expand(opt_idx, NULL);
+ p = option_expand(opt_idx, NULL);
}
if (p != NULL) {
p = xstrdup(p);
@@ -391,7 +392,7 @@ void set_init_1(bool clean_arg)
if (options[opt_idx].flags & P_DEF_ALLOCED) {
xfree(options[opt_idx].def_val);
}
- options[opt_idx].def_val = (char_u *)p;
+ options[opt_idx].def_val = p;
options[opt_idx].flags |= P_DEF_ALLOCED;
}
}
@@ -404,7 +405,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();
@@ -419,12 +420,12 @@ void set_init_1(bool clean_arg)
// use utf-8 as 'default' if locale encoding can't be detected.
p = (char_u *)xmemdupz(S_LEN("utf-8"));
}
- fenc_default = p;
+ fenc_default = (char *)p;
#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 +441,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) {
@@ -448,12 +449,12 @@ static void set_option_default(int opt_idx, int opt_flags)
// freeing and allocating the value.
if (options[opt_idx].indir != PV_NONE) {
set_string_option_direct(NULL, opt_idx,
- (char *)options[opt_idx].def_val, opt_flags, 0);
+ 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;
+ *(char **)varp = options[opt_idx].def_val;
options[opt_idx].flags &= ~P_ALLOCED;
}
} else if (flags & P_NUM) {
@@ -532,9 +533,7 @@ static void set_string_default(const char *name, char *val, bool allocated)
xfree(options[opt_idx].def_val);
}
- options[opt_idx].def_val = allocated
- ? (char_u *)val
- : (char_u *)xstrdup(val);
+ options[opt_idx].def_val = allocated ? val : xstrdup(val);
options[opt_idx].flags |= P_DEF_ALLOCED;
}
}
@@ -578,7 +577,7 @@ void set_number_default(char *name, long val)
opt_idx = findoption(name);
if (opt_idx >= 0) {
- options[opt_idx].def_val = (char_u *)(intptr_t)val;
+ options[opt_idx].def_val = (char *)(intptr_t)val;
}
}
@@ -590,14 +589,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);
}
} 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();
@@ -620,10 +619,8 @@ void set_init_2(bool headless)
}
comp_col();
- /*
- * 'window' is only for backwards compatibility with Vi.
- * Default is Rows - 1.
- */
+ // 'window' is only for backwards compatibility with Vi.
+ // Default is Rows - 1.
if (!option_was_set("window")) {
p_window = Rows - 1;
}
@@ -649,41 +646,41 @@ void set_init_3(void)
: !(options[idx_sp].flags & P_WAS_SET);
size_t len = 0;
- char_u *p = (char_u *)invocation_path_tail(p_sh, &len);
- p = vim_strnsave(p, len);
+ char *p = (char *)invocation_path_tail((char_u *)p_sh, &len);
+ p = xstrnsave(p, len);
{
//
// Default for p_sp is "| tee", for p_srr is ">".
// For known shells it is changed here to include stderr.
//
- if (FNAMECMP(p, "csh") == 0
- || FNAMECMP(p, "tcsh") == 0) {
+ if (path_fnamecmp(p, "csh") == 0
+ || path_fnamecmp(p, "tcsh") == 0) {
if (do_sp) {
- p_sp = (char_u *)"|& tee";
+ p_sp = "|& tee";
options[idx_sp].def_val = p_sp;
}
if (do_srr) {
- p_srr = (char_u *)">&";
+ p_srr = ">&";
options[idx_srr].def_val = p_srr;
}
- } else if (FNAMECMP(p, "sh") == 0
- || FNAMECMP(p, "ksh") == 0
- || FNAMECMP(p, "mksh") == 0
- || FNAMECMP(p, "pdksh") == 0
- || FNAMECMP(p, "zsh") == 0
- || FNAMECMP(p, "zsh-beta") == 0
- || FNAMECMP(p, "bash") == 0
- || FNAMECMP(p, "fish") == 0
- || FNAMECMP(p, "ash") == 0
- || FNAMECMP(p, "dash") == 0) {
+ } else if (path_fnamecmp(p, "sh") == 0
+ || path_fnamecmp(p, "ksh") == 0
+ || path_fnamecmp(p, "mksh") == 0
+ || path_fnamecmp(p, "pdksh") == 0
+ || path_fnamecmp(p, "zsh") == 0
+ || path_fnamecmp(p, "zsh-beta") == 0
+ || path_fnamecmp(p, "bash") == 0
+ || path_fnamecmp(p, "fish") == 0
+ || path_fnamecmp(p, "ash") == 0
+ || path_fnamecmp(p, "dash") == 0) {
// Always use POSIX shell style redirection if we reach this
if (do_sp) {
- p_sp = (char_u *)"2>&1| tee";
+ p_sp = "2>&1| tee";
options[idx_sp].def_val = p_sp;
}
if (do_srr) {
- p_srr = (char_u *)">%s 2>&1";
+ p_srr = ">%s 2>&1";
options[idx_srr].def_val = p_srr;
}
}
@@ -717,7 +714,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".
@@ -743,19 +740,17 @@ void set_title_defaults(void)
{
int idx1;
- /*
- * If GUI is (going to be) used, we can always set the window title and
- * icon name. Saves a bit of time, because the X11 display server does
- * not need to be contacted.
- */
+ // If GUI is (going to be) used, we can always set the window title and
+ // icon name. Saves a bit of time, because the X11 display server does
+ // not need to be contacted.
idx1 = findoption("title");
if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) {
- options[idx1].def_val = (char_u *)(intptr_t)0;
+ options[idx1].def_val = 0;
p_title = 0;
}
idx1 = findoption("icon");
if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) {
- options[idx1].def_val = (char_u *)(intptr_t)0;
+ options[idx1].def_val = 0;
p_icon = 0;
}
}
@@ -795,7 +790,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,14 +813,12 @@ 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)) {
- /*
- * ":set all" show all options.
- * ":set all&" set all options to their default value.
- */
+ // ":set all" show all options.
+ // ":set all&" set all options to their default value.
arg += 3;
if (*arg == '&') {
arg++;
@@ -834,7 +827,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 +908,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 +919,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 +946,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
@@ -1001,9 +994,7 @@ int do_set(char *arg, int opt_flags)
|| (prefix == 1
&& vim_strchr("=:&<", nextchar) == NULL
&& !(flags & P_BOOL))) {
- /*
- * print value
- */
+ // print value
if (did_show) {
msg_putchar('\n'); // cursor below last one
} else {
@@ -1025,7 +1016,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 != '?'
@@ -1042,11 +1033,9 @@ int do_set(char *arg, int opt_flags)
goto skip;
}
- /*
- * ":set opt!": invert
- * ":set opt&": reset to default value
- * ":set opt<": reset to global value
- */
+ // ":set opt!": invert
+ // ":set opt&": reset to default value
+ // ":set opt<": reset to global value
if (nextchar == '!') {
value = *(int *)(varp) ^ 1;
} else if (nextchar == '&') {
@@ -1061,10 +1050,8 @@ int do_set(char *arg, int opt_flags)
OPT_GLOBAL);
}
} else {
- /*
- * ":set invopt": invert
- * ":set opt" or ":set noopt": set or reset
- */
+ // ":set invopt": invert
+ // ":set opt" or ":set noopt": set or reset
if (nextchar != NUL && !ascii_iswhite(afterchar)) {
errmsg = e_trailing;
goto skip;
@@ -1116,13 +1103,13 @@ int do_set(char *arg, int opt_flags)
}
} else if (*arg == '-' || ascii_isdigit(*arg)) {
// Allow negative, octal and hex numbers.
- vim_str2nr((char_u *)arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true);
+ vim_str2nr(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;
}
@@ -1140,9 +1127,9 @@ int do_set(char *arg, int opt_flags)
opt_flags);
} else if (opt_idx >= 0) { // String.
char_u *save_arg = NULL;
- char_u *s = NULL;
+ char *s = NULL;
char_u *oldval = NULL; // previous value if *varp
- char_u *newval;
+ char *newval;
char_u *origval = NULL;
char_u *origval_l = NULL;
char_u *origval_g = NULL;
@@ -1172,7 +1159,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;
}
}
@@ -1198,12 +1185,12 @@ int do_set(char *arg, int opt_flags)
if (s == NULL) {
s = newval;
}
- newval = vim_strsave(s);
+ newval = xstrdup(s);
} else {
- newval = (char_u *)xstrdup((char *)newval);
+ newval = xstrdup(newval);
}
} else if (nextchar == '<') { // set to global val
- newval = vim_strsave(*(char_u **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL));
+ newval = xstrdup(*(char **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL));
} else {
arg++; // jump to after the '=' or ':'
@@ -1220,16 +1207,16 @@ 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");
+ *(char_u **)varp = (char_u *)xstrdup("indent,eol");
break;
case 2:
- *(char_u **)varp = vim_strsave((char_u *)"indent,eol,start");
+ *(char_u **)varp = (char_u *)xstrdup("indent,eol,start");
break;
case 3:
- *(char_u **)varp = vim_strsave((char_u *)"indent,eol,nostop");
+ *(char_u **)varp = (char_u *)xstrdup("indent,eol,nostop");
break;
}
xfree(oldval);
@@ -1250,19 +1237,19 @@ int do_set(char *arg, int opt_flags)
*errbuf = NUL;
i = getdigits_int(&arg, true, 0);
if (i & 1) {
- STRLCAT(errbuf, "b,", sizeof(errbuf));
+ xstrlcat(errbuf, "b,", sizeof(errbuf));
}
if (i & 2) {
- STRLCAT(errbuf, "s,", sizeof(errbuf));
+ xstrlcat(errbuf, "s,", sizeof(errbuf));
}
if (i & 4) {
- STRLCAT(errbuf, "h,l,", sizeof(errbuf));
+ xstrlcat(errbuf, "h,l,", sizeof(errbuf));
}
if (i & 8) {
- STRLCAT(errbuf, "<,>,", sizeof(errbuf));
+ xstrlcat(errbuf, "<,>,", sizeof(errbuf));
}
if (i & 16) {
- STRLCAT(errbuf, "[,],", sizeof(errbuf));
+ xstrlcat(errbuf, "[,],", sizeof(errbuf));
}
save_arg = (char_u *)arg;
arg = errbuf;
@@ -1274,11 +1261,10 @@ int do_set(char *arg, int opt_flags)
arg++;
}
- /*
- * Copy the new string into allocated memory.
- * Can't use set_string_option_direct(), because
- * we need to remove the backslashes.
- */
+ // Copy the new string into allocated memory.
+ // Can't use set_string_option_direct(), because
+ // we need to remove the backslashes.
+
// get a bit too much
newlen = (unsigned)STRLEN(arg) + 1;
if (adding || prepending || removing) {
@@ -1287,14 +1273,12 @@ int do_set(char *arg, int opt_flags)
newval = xmalloc(newlen);
s = newval;
- /*
- * Copy the string, skip over escaped chars.
- * For WIN32 backslashes before normal
- * file name characters are not removed, and keep
- * backslash at start, for "\\machine\path", but
- * do remove it for "\\\\machine\\path".
- * The reverse is found in ExpandOldSetting().
- */
+ // Copy the string, skip over escaped chars.
+ // For WIN32 backslashes before normal
+ // file name characters are not removed, and keep
+ // backslash at start, for "\\machine\path", but
+ // do remove it for "\\\\machine\\path".
+ // The reverse is found in ExpandOldSetting().
while (*arg && !ascii_iswhite(*arg)) {
if (*arg == '\\' && arg[1] != NUL
#ifdef BACKSLASH_IN_FILENAME
@@ -1315,16 +1299,14 @@ int do_set(char *arg, int opt_flags)
arg += i;
s += i;
} else {
- *s++ = (uint8_t)(*arg++);
+ *s++ = *arg++;
}
}
*s = NUL;
- /*
- * Expand environment variables and ~.
- * Don't do it when adding without inserting a
- * comma.
- */
+ // Expand environment variables and ~.
+ // Don't do it when adding without inserting a
+ // comma.
if (!(adding || prepending || removing)
|| (flags & P_COMMA)) {
s = option_expand(opt_idx, newval);
@@ -1344,7 +1326,7 @@ int do_set(char *arg, int opt_flags)
i = 0; // init for GCC
if (removing || (flags & P_NODUP)) {
i = (int)STRLEN(newval);
- s = find_dup_item(origval, newval, flags);
+ s = (char *)find_dup_item(origval, (char_u *)newval, flags);
// do not add if already there
if ((adding || prepending) && s != NULL) {
@@ -1356,7 +1338,7 @@ int do_set(char *arg, int opt_flags)
// if no duplicate, move pointer to end of
// original value
if (s == NULL) {
- s = origval + (int)STRLEN(origval);
+ s = (char *)origval + (int)STRLEN(origval);
}
}
@@ -1393,7 +1375,7 @@ int do_set(char *arg, int opt_flags)
if (*s) {
// may need to remove a comma
if (flags & P_COMMA) {
- if (s == origval) {
+ if (s == (char *)origval) {
// include comma after string
if (s[i] == ',') {
i++;
@@ -1404,7 +1386,7 @@ int do_set(char *arg, int opt_flags)
i++;
}
}
- STRMOVE(newval + (s - origval), s + i);
+ STRMOVE(newval + (s - (char *)origval), s + i);
}
}
@@ -1415,14 +1397,14 @@ int do_set(char *arg, int opt_flags)
// 'whichwrap'
if (flags & P_ONECOMMA) {
if (*s != ',' && *(s + 1) == ','
- && vim_strchr((char *)s + 2, *s) != NULL) {
+ && vim_strchr(s + 2, *s) != NULL) {
// Remove the duplicated value and the next comma.
STRMOVE(s, s + 2);
continue;
}
} else {
if ((!(flags & P_COMMA) || *s != ',')
- && vim_strchr((char *)s + 1, *s) != NULL) {
+ && vim_strchr(s + 1, *s) != NULL) {
STRMOVE(s, s + 1);
continue;
}
@@ -1437,7 +1419,7 @@ int do_set(char *arg, int opt_flags)
}
// Set the new value.
- *(char_u **)(varp) = newval;
+ *(char_u **)(varp) = (char_u *)newval;
// origval may be freed by
// did_set_string_option(), make a copy.
@@ -1447,7 +1429,7 @@ int do_set(char *arg, int opt_flags)
// newval (and varp) may become invalid if the
// buffer is closed by autocommands.
- saved_newval = (newval != NULL) ? xstrdup((char *)newval) : 0;
+ saved_newval = (newval != NULL) ? xstrdup(newval) : 0;
{
uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags);
@@ -1468,7 +1450,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);
@@ -1506,12 +1488,10 @@ int do_set(char *arg, int opt_flags)
}
skip:
- /*
- * Advance to next argument.
- * - skip until a blank found, taking care of backslashes
- * - skip blanks
- * - skip one "=val" argument (for hidden options ":set gfn =xx")
- */
+ // Advance to next argument.
+ // - skip until a blank found, taking care of backslashes
+ // - skip blanks
+ // - skip one "=val" argument (for hidden options ":set gfn =xx")
for (i = 0; i < 2; i++) {
while (*arg != NUL && !ascii_iswhite(*arg)) {
if (*arg++ == '\\' && *arg != NUL) {
@@ -1528,17 +1508,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 +1567,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 +1578,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
@@ -1632,10 +1594,8 @@ void did_set_title(void)
/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL
void set_options_bin(int oldval, int newval, int opt_flags)
{
- /*
- * The option values that are changed when 'bin' changes are
- * copied when 'bin is set and restored when 'bin' is reset.
- */
+ // The option values that are changed when 'bin' changes are
+ // copied when 'bin is set and restored when 'bin' is reset.
if (newval) {
if (!oldval) { // switched on
if (!(opt_flags & OPT_GLOBAL)) {
@@ -1702,16 +1662,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;
}
@@ -1723,7 +1681,7 @@ char_u *find_shada_parameter(int type)
/// These string options cannot be indirect!
/// If "val" is NULL expand the current value of the option.
/// Return pointer to NameBuff, or NULL when not expanded.
-static char_u *option_expand(int opt_idx, char_u *val)
+static char *option_expand(int opt_idx, char *val)
{
// if option doesn't need expansion nothing to do
if (!(options[opt_idx].flags & P_EXPAND) || options[opt_idx].var == NULL) {
@@ -1731,7 +1689,7 @@ static char_u *option_expand(int opt_idx, char_u *val)
}
if (val == NULL) {
- val = *(char_u **)options[opt_idx].var;
+ val = *(char **)options[opt_idx].var;
}
// If val is longer than MAXPATHL no meaningful expansion can be done,
@@ -1740,17 +1698,15 @@ static char_u *option_expand(int opt_idx, char_u *val)
return NULL;
}
- /*
- * Expanding this with NameBuff, expand_env() must not be passed IObuff.
- * Escape spaces when expanding 'tags', they are used to separate file
- * names.
- * For 'spellsuggest' expand after "file:".
- */
- expand_env_esc(val, NameBuff, MAXPATHL,
+ // Expanding this with NameBuff, expand_env() must not be passed IObuff.
+ // Escape spaces when expanding 'tags', they are used to separate file
+ // names.
+ // For 'spellsuggest' expand after "file:".
+ expand_env_esc((char_u *)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
+ if (strcmp(NameBuff, val) == 0) { // they are the same
return NULL;
}
@@ -1804,7 +1760,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 +1819,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 +1927,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 +2032,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 +2049,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,18 +2108,13 @@ 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);
}
}
if ((int *)varp == &curwin->w_p_arab) {
if (curwin->w_p_arab) {
- /*
- * 'arabic' is set, handle various sub-settings.
- */
+ // 'arabic' is set, handle various sub-settings.
if (!p_tbidi) {
// set rightleft mode
if (!curwin->w_p_rl) {
@@ -2173,13 +2125,13 @@ 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);
}
}
// Arabic requires a utf-8 encoding, inform the user if it's not
// set.
- if (STRCMP(p_enc, "utf-8") != 0) {
+ if (strcmp(p_enc, "utf-8") != 0) {
static char *w_arabic = N_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'");
msg_source(HL_ATTR(HLF_W));
@@ -2191,11 +2143,9 @@ 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.
- */
+ // 'arabic' is reset, handle various sub-settings.
if (!p_tbidi) {
// reset rightleft mode
if (curwin->w_p_rl) {
@@ -2216,9 +2166,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
}
}
- /*
- * End of handling side effects for bool options.
- */
+ // End of handling side effects for bool options.
// after handling side effects, call autocommand
@@ -2271,7 +2219,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 +2678,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);
}
}
@@ -2808,7 +2756,7 @@ int findoption_len(const char *const arg, const size_t len)
if (STRLEN(options[opt_idx].fullname) == 7) {
return findoption_len("shada", 5);
}
- assert(STRCMP(options[opt_idx].fullname, "viminfofile") == 0);
+ assert(strcmp(options[opt_idx].fullname, "viminfofile") == 0);
return findoption_len("shadafile", 9);
}
}
@@ -2888,7 +2836,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 +2846,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 +2885,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 +3011,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 +3019,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 +3095,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 +3125,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 +3165,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 +3254,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);
@@ -3323,9 +3283,7 @@ static void showoptions(int all, int opt_flags)
}
}
- /*
- * display the items
- */
+ // display the items
if (run == 1) {
assert(Columns <= INT_MAX - GAP
&& Columns + GAP >= INT_MIN + 3
@@ -3350,7 +3308,6 @@ static void showoptions(int all, int opt_flags)
showoneopt(items[i], opt_flags);
col += INC;
}
- ui_flush();
os_breakcheck();
}
}
@@ -3370,7 +3327,7 @@ static int optval_default(vimoption_T *p, char_u *varp)
return *(int *)varp == (int)(intptr_t)p->def_val;
}
// P_STRING
- return STRCMP(*(char_u **)varp, p->def_val) == 0;
+ return strcmp(*(char **)varp, p->def_val) == 0;
}
/// Send update to UIs with values of UI relevant options
@@ -3405,13 +3362,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,22 +3413,20 @@ 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;
int round;
int pri;
- /*
- * Some options are never written:
- * - Options that don't have a default (terminal name, columns, lines).
- * - Terminal options.
- * - Hidden options.
- *
- * Do the loop over "options[]" twice: once for options with the
- * P_PRI_MKRC flag and once without.
- */
+ // Some options are never written:
+ // - Options that don't have a default (terminal name, columns, lines).
+ // - Terminal options.
+ // - Hidden options.
+ //
+ // Do the loop over "options[]" twice: once for options with the
+ // P_PRI_MKRC flag and once without.
for (pri = 1; pri >= 0; pri--) {
for (p = &options[0]; p->fullname; p++) {
if (!(p->flags & P_NO_MKRC)
@@ -3494,7 +3448,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 +3467,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 +3479,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 +3507,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 +3528,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 +3556,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 +3569,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 +3603,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 +3729,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 +3743,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 +3758,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);
}
@@ -4094,6 +4043,8 @@ static char_u *get_varp(vimoption_T *p)
return (char_u *)&(curbuf->b_p_cfu);
case PV_OFU:
return (char_u *)&(curbuf->b_p_ofu);
+ case PV_URF:
+ return (char_u *)&(curbuf->b_p_urf);
case PV_EOL:
return (char_u *)&(curbuf->b_p_eol);
case PV_FIXEOL:
@@ -4170,6 +4121,8 @@ static char_u *get_varp(vimoption_T *p)
return (char_u *)&(curbuf->b_p_sw);
case PV_TFU:
return (char_u *)&(curbuf->b_p_tfu);
+ case PV_UMF:
+ return (char_u *)&(curbuf->b_p_umf);
case PV_TS:
return (char_u *)&(curbuf->b_p_ts);
case PV_TW:
@@ -4215,7 +4168,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.
@@ -4227,6 +4180,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.
@@ -4235,21 +4196,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;
@@ -4257,32 +4220,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.
@@ -4317,10 +4276,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.
@@ -4343,10 +4302,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)
@@ -4396,10 +4355,8 @@ void buf_copy_options(buf_T *buf, int flags)
int dont_do_help;
int did_isk = false;
- /*
- * Skip this when the option defaults have not been set yet. Happens when
- * main() allocates the first buffer.
- */
+ // Skip this when the option defaults have not been set yet. Happens when
+ // main() allocates the first buffer.
if (p_cpo != NULL) {
//
// Always copy when entering and 'cpo' contains 'S'.
@@ -4428,7 +4385,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,
@@ -4436,19 +4393,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;
@@ -4493,42 +4450,44 @@ 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);
+ buf->b_p_csl = xstrdup(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_tfu = vim_strsave(p_tfu);
+ buf->b_p_urf = xstrdup(p_urf);
+ COPY_OPT_SCTX(buf, BV_URF);
+ buf->b_p_tfu = xstrdup(p_tfu);
COPY_OPT_SCTX(buf, BV_TFU);
+ buf->b_p_umf = xstrdup(p_umf);
+ COPY_OPT_SCTX(buf, BV_UMF);
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);
@@ -4538,18 +4497,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);
@@ -4558,25 +4517,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
@@ -4603,38 +4562,36 @@ 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);
buf->b_p_lw = empty_option;
buf->b_p_menc = empty_option;
- /*
- * Don't copy the options set by ex_help(), use the saved values,
- * when going from a help buffer to a non-help buffer.
- * Don't touch these at all when BCO_NOHELP is used and going from
- * or to a help buffer.
- */
+ // Don't copy the options set by ex_help(), use the saved values,
+ // when going from a help buffer to a non-help buffer.
+ // Don't touch these at all when BCO_NOHELP is used and going from
+ // 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);
@@ -4650,10 +4607,8 @@ void buf_copy_options(buf_T *buf, int flags)
}
}
- /*
- * When the options should be copied (ignoring BCO_ALWAYS), set the
- * flag that indicates that the options have been initialized.
- */
+ // When the options should be copied (ignoring BCO_ALWAYS), set the
+ // flag that indicates that the options have been initialized.
if (should_copy) {
buf->b_p_initialized = true;
}
@@ -4877,7 +4832,7 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***fi
int num_normal = 0; // Nr of matching non-term-code settings
int match;
int count = 0;
- char_u *str;
+ char *str;
int loop;
static char *(names[]) = { "all" };
int ic = regmatch->rm_ic; // remember the ignore-case flag
@@ -4899,7 +4854,7 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***fi
}
}
}
- for (size_t opt_idx = 0; (str = (char_u *)options[opt_idx].fullname) != NULL;
+ for (size_t opt_idx = 0; (str = options[opt_idx].fullname) != NULL;
opt_idx++) {
if (options[opt_idx].var == NULL) {
continue;
@@ -4909,7 +4864,7 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***fi
continue;
}
match = false;
- if (vim_regexec(regmatch, (char *)str, (colnr_T)0)
+ if (vim_regexec(regmatch, str, (colnr_T)0)
|| (options[opt_idx].shortname != NULL
&& vim_regexec(regmatch,
options[opt_idx].shortname,
@@ -4921,7 +4876,7 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***fi
if (loop == 0) {
num_normal++;
} else {
- (*file)[count++] = (char *)vim_strsave(str);
+ (*file)[count++] = xstrdup(str);
}
}
}
@@ -4932,7 +4887,7 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***fi
} else {
return OK;
}
- *file = xmalloc((size_t)(*num_file) * sizeof(char_u *));
+ *file = xmalloc((size_t)(*num_file) * sizeof(char *));
}
}
return OK;
@@ -4945,9 +4900,7 @@ void ExpandOldSetting(int *num_file, char ***file)
*num_file = 0;
*file = xmalloc(sizeof(char_u *));
- /*
- * For a terminal key code expand_option_idx is < 0.
- */
+ // For a terminal key code expand_option_idx is < 0.
if (expand_option_idx < 0) {
expand_option_idx = findoption((const char *)expand_option_name);
}
@@ -4955,7 +4908,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 *)"";
}
@@ -4988,9 +4941,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;
@@ -5012,7 +4963,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);
@@ -5034,25 +4985,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.
@@ -5066,10 +5006,8 @@ static void paste_option_changed(void)
static int save_hkmap = 0;
if (p_paste) {
- /*
- * Paste switched from off to on.
- * Save the current values, so they can be restored later.
- */
+ // Paste switched from off to on.
+ // Save the current values, so they can be restored later.
if (!old_p_paste) {
// save options for each buffer
FOR_ALL_BUFFERS(buf) {
@@ -5082,7 +5020,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;
}
@@ -5101,9 +5039,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
@@ -5153,9 +5089,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);
@@ -5182,7 +5116,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;
@@ -5250,16 +5184,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) {
@@ -5302,7 +5236,7 @@ int fill_culopt_flags(char_u *val, win_T *wp)
/// Set the callback function value for an option that accepts a function name,
/// lambda, et al. (e.g. 'operatorfunc', 'tagfunc', etc.)
/// @return OK if the option is successfully set to a function, otherwise FAIL
-int option_set_callback_func(char_u *optval, Callback *optcb)
+int option_set_callback_func(char *optval, Callback *optcb)
{
if (optval == NULL || *optval == NUL) {
callback_free(optcb);
@@ -5314,7 +5248,7 @@ int option_set_callback_func(char_u *optval, Callback *optcb)
|| (STRNCMP(optval, "function(", 9) == 0)
|| (STRNCMP(optval, "funcref(", 8) == 0)) {
// Lambda expression or a funcref
- tv = eval_expr((char *)optval);
+ tv = eval_expr(optval);
if (tv == NULL) {
return FAIL;
}
@@ -5322,7 +5256,7 @@ int option_set_callback_func(char_u *optval, Callback *optcb)
// treat everything else as a function name string
tv = xcalloc(1, sizeof(*tv));
tv->v_type = VAR_STRING;
- tv->vval.v_string = (char *)vim_strsave(optval);
+ tv->vval.v_string = xstrdup(optval);
}
Callback cb;
@@ -5337,59 +5271,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)
@@ -5407,99 +5288,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'.
@@ -5524,19 +5313,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;
+ if (strcmp(win->w_p_sbr, "NONE") == 0) {
+ 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;
@@ -5563,7 +5352,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;
@@ -5620,7 +5409,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++;
@@ -5628,7 +5417,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`.
@@ -5663,7 +5452,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;
@@ -5672,13 +5461,13 @@ size_t copy_option_part(char **option, char *buf, size_t maxlen, char *sep_chars
/// Return true when 'shell' has "csh" in the tail.
int csh_like_shell(void)
{
- return strstr(path_tail((char *)p_sh), "csh") != NULL;
+ return strstr(path_tail(p_sh), "csh") != NULL;
}
/// Return true when 'shell' has "fish" in the tail.
bool fish_like_shell(void)
{
- return strstr(path_tail((char *)p_sh), "fish") != NULL;
+ return strstr(path_tail(p_sh), "fish") != NULL;
}
/// Return the number of requested sign columns, based on current
@@ -5836,7 +5625,7 @@ static Dictionary vimoption2dict(vimoption_T *opt)
const char *type;
Object def;
// TODO(bfredl): do you even nocp?
- char_u *def_val = opt->def_val;
+ char_u *def_val = (char_u *)opt->def_val;
if (opt->flags & P_STRING) {
type = "string";
def = CSTR_TO_OBJ(def_val ? (char *)def_val : "");
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index ad8092add2..589be702f7 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, \
})
@@ -379,12 +379,10 @@ enum {
#define LISPWORD_VALUE \
"defun,define,defmacro,set!,lambda,if,case,let,flet,let*,letrec,do,do*,define-syntax,let-syntax,letrec-syntax,destructuring-bind,defpackage,defparameter,defstruct,deftype,defvar,do-all-symbols,do-external-symbols,do-symbols,dolist,dotimes,ecase,etypecase,eval-when,labels,macrolet,multiple-value-bind,multiple-value-call,multiple-value-prog1,multiple-value-setq,prog1,progv,typecase,unless,unwind-protect,when,with-input-from-string,with-open-file,with-open-stream,with-output-to-string,with-package-iterator,define-condition,handler-bind,handler-case,restart-bind,restart-case,with-simple-restart,store-value,use-value,muffle-warning,abort,continue,with-slots,with-slots*,with-accessors,with-accessors*,defclass,defmethod,print-unreadable-object"
-/*
- * The following are actual variables for the options
- */
+// The following are actual variables for the options
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 +390,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 +438,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 +495,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 *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 +531,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 +608,61 @@ 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_mousemev; ///< 'mousemoveevent'
+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 +684,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 *p_sh; // 'shell'
+EXTERN char_u *p_shcf; // 'shellcmdflag'
+EXTERN char *p_sp; // 'shellpipe'
+EXTERN char_u *p_shq; // 'shellquote'
+EXTERN char *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 +712,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 +726,18 @@ 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_umf; ///< 'usermarkfunc'
+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 unsigned int spo_flags;
+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 +746,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 +768,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 +779,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 +799,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,6 +826,7 @@ EXTERN int p_wa; // 'writeany'
EXTERN int p_wb; // 'writebackup'
EXTERN long p_wd; // 'writedelay'
EXTERN int p_cdh; // 'cdhome'
+EXTERN char *p_urf; // 'userregister'
EXTERN int p_force_on; ///< options that cannot be turned off.
EXTERN int p_force_off; ///< options that cannot be turned on.
@@ -910,6 +912,7 @@ enum {
BV_SW,
BV_SWF,
BV_TFU,
+ BV_UMF,
BV_TSRFU,
BV_TAGS,
BV_TC,
@@ -921,14 +924,13 @@ enum {
BV_WM,
BV_VSTS,
BV_VTS,
+ BV_URF,
BV_COUNT, // must be the last one
};
-/*
- * "indir" values for window-local options.
- * These need to be defined globally, so that the WV_COUNT can be used in the
- * window structure.
- */
+// "indir" values for window-local options.
+// These need to be defined globally, so that the WV_COUNT can be used in the
+// window structure.
enum {
WV_LIST = 0,
WV_ARAB,
@@ -972,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
@@ -992,4 +994,4 @@ typedef struct {
uint64_t channel_id; /// Only used when script_id is SID_API_CLIENT.
} LastSet;
-#endif // NVIM_OPTION_DEFS_H
+#endif // NVIM_OPTION_DEFS_H
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 2f941f5d0c..7456d8ae4f 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -1622,6 +1622,14 @@ return {
defaults={if_true="popup_setpos"}
},
{
+ full_name='mousemoveevent', abbreviation='mousemev',
+ short_desc=N_("deliver mouse move events to input queue"),
+ type='bool', scope={'global'},
+ redraw={'ui_option'},
+ varname='p_mousemev',
+ defaults={if_true=false}
+ },
+ {
full_name='mousescroll',
short_desc=N_("amount to scroll by when scrolling with a mouse"),
type='string', list='comma', scope={'global'},
@@ -2347,6 +2355,7 @@ return {
secure=true,
expand=true,
varname='p_spo',
+ redraw={'current_buffer'},
defaults={if_true=""}
},
{
@@ -2691,6 +2700,20 @@ return {
defaults={if_true=4000}
},
{
+ full_name='usermarkfunc', abbreviation='umf',
+ short_desc=N_("function used to perform jumps/sets to user marks."),
+ type='string', scope={'buffer'},
+ varname='p_umf',
+ defaults={if_true=""}
+ },
+ {
+ full_name='userregfunc', abbreviation='urf',
+ short_desc=N_("Function used to define behavior of user-defined registers."),
+ type='string', scope={'buffer'},
+ varname='p_urf',
+ defaults={if_true=""}
+ },
+ {
full_name='varsofttabstop', abbreviation='vsts',
short_desc=N_("list of numbers of spaces that <Tab> uses while editing"),
type='string', list='comma', scope={'buffer'},
@@ -2859,7 +2882,8 @@ return {
{
full_name='winhighlight', abbreviation='winhl',
short_desc=N_("Setup window-local highlights");
- type='string', scope={'window'},
+ type='string', list='onecomma', scope={'window'},
+ deny_duplicates=true,
alloced=true,
redraw={'current_window'},
defaults={if_true=""}
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index c50225dfdf..9d21603754 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 };
@@ -100,16 +107,17 @@ static char *(p_fdc_values[]) = { "auto", "auto:1", "auto:2", "auto:3", "auto:4"
"auto:6", "auto:7", "auto:8", "auto:9", "0", "1", "2", "3", "4",
"5", "6", "7", "8", "9", NULL };
static char *(p_cb_values[]) = { "unnamed", "unnamedplus", NULL };
+static char *(p_spo_values[]) = { "camel", "noplainbuffer", NULL };
static char *(p_icm_values[]) = { "nosplit", "split", NULL };
static char *(p_jop_values[]) = { "stack", "view", NULL };
static char *(p_tpf_values[]) = { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NULL };
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.
@@ -245,17 +253,17 @@ void check_buf_options(buf_T *buf)
/// Free the string allocated for an option.
/// Checks for the string being empty_option. This may happen if we're out of
-/// memory, vim_strsave() returned NULL, which was replaced by empty_option by
+/// memory, xstrdup() 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 +271,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 +282,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 +334,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 +348,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 +389,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 +421,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 +444,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 +521,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 +632,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;
}
@@ -677,9 +683,9 @@ 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,
+ 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 +719,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)) {
@@ -725,7 +731,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
}
}
} else if (varp == &p_hl) { // 'highlight'
- if (STRCMP(*varp, HIGHLIGHT_INIT) != 0) {
+ if (strcmp(*varp, HIGHLIGHT_INIT) != 0) {
errmsg = e_unsupportedoption;
}
} else if (varp == &p_jop) { // 'jumpoptions'
@@ -753,8 +759,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 +781,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 +810,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;
@@ -817,13 +823,13 @@ 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);
+ // canonize the value, so that strcmp() can be used on it
+ 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) {
+ if (strcmp(p_enc, "utf-8") != 0) {
errmsg = e_unsupportedoption;
} else {
spell_reload();
@@ -832,9 +838,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 +895,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 +924,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 +947,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 +993,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 +1038,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 +1059,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 +1078,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;
@@ -1127,7 +1126,8 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
// When 'spellcapcheck' is set compile the regexp program.
errmsg = compile_cap_prog(curwin->w_s);
} else if (varp == &(curwin->w_s->b_p_spo)) { // 'spelloptions'
- if (**varp != NUL && STRCMP("camel", *varp) != 0) {
+ if (opt_strings_flags(curwin->w_s->b_p_spo, p_spo_values, &(curwin->w_s->b_p_spo_flags),
+ true) != OK) {
errmsg = e_invarg;
}
} else if (varp == &p_sps) { // 'spellsuggest'
@@ -1152,29 +1152,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 +1185,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 +1247,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 +1257,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 +1282,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 +1293,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 +1319,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 +1344,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) {
@@ -1356,7 +1358,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
} else {
if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) {
errmsg = e_invarg;
- } else if (STRCMP(p_ve, oldval) != 0) {
+ } else if (strcmp(p_ve, oldval) != 0) {
// Recompute cursor position in case the new 've' setting
// changes something.
validate_virtcol();
@@ -1365,7 +1367,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
@@ -1391,7 +1393,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
if (!valid_filetype(*varp)) {
errmsg = e_invarg;
} else {
- value_changed = STRCMP(oldval, *varp) != 0;
+ value_changed = strcmp(oldval, *varp) != 0;
// Since we check the value, there is no need to set P_INSECURE,
// even when the value comes from a modeline.
@@ -1401,7 +1403,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er
if (!valid_filetype(*varp)) {
errmsg = e_invarg;
} else {
- value_changed = STRCMP(oldval, *varp) != 0;
+ value_changed = strcmp(oldval, *varp) != 0;
// Since we check the value, there is no need to set P_INSECURE,
// even when the value comes from a modeline.
@@ -1416,7 +1418,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 +1443,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 +1485,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 +1496,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 +1528,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 +1544,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 +1564,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 +1575,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 +1587,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 +1618,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 +1631,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 +1659,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..34ed3aaf6e 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -476,7 +476,7 @@ void init_homedir(void)
// Change to the directory and get the actual path. This resolves
// links. Don't do it when we can't return.
if (os_dirname((char_u *)os_buf, MAXPATHL) == OK && os_chdir(os_buf) == 0) {
- if (!os_chdir(var) && os_dirname(IObuff, IOSIZE) == OK) {
+ if (!os_chdir(var) && os_dirname((char_u *)IObuff, IOSIZE) == OK) {
var = (char *)IObuff;
}
if (os_chdir(os_buf) != 0) {
@@ -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.
@@ -669,8 +669,8 @@ void expand_env_esc(char_u *restrict srcp, char_u *restrict dst, int dstlen, boo
ExpandInit(&xpc);
xpc.xp_context = EXPAND_FILES;
- var = ExpandOne(&xpc, dst, NULL,
- WILD_ADD_SLASH|WILD_SILENT, WILD_EXPAND_FREE);
+ var = (char_u *)ExpandOne(&xpc, (char *)dst, NULL,
+ WILD_ADD_SLASH|WILD_SILENT, WILD_EXPAND_FREE);
mustfree = true;
}
#else
@@ -684,7 +684,7 @@ void expand_env_esc(char_u *restrict srcp, char_u *restrict dst, int dstlen, boo
// If 'shellslash' is set change backslashes to forward slashes.
// Can't use slash_adjust(), p_ssl may be set temporarily.
if (p_ssl && var != NULL && vim_strchr(var, '\\') != NULL) {
- char_u *p = vim_strsave(var);
+ char_u *p = xstrdup(var);
if (mustfree) {
xfree(var);
@@ -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);
@@ -804,7 +804,7 @@ static char *remove_tail(char *path, char *pend, char *dirname)
char *new_tail = pend - len - 1;
if (new_tail >= path
- && FNAMENCMP((char_u *)new_tail, (char_u *)dirname, len) == 0
+ && path_fnamencmp(new_tail, dirname, len) == 0
&& (new_tail == path || after_pathsep(path, new_tail))) {
return new_tail;
}
@@ -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;
}
@@ -1098,7 +1098,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si
size_t len = dirlen;
for (;;) {
if (len
- && FNAMENCMP(src, (char_u *)p, len) == 0
+ && path_fnamencmp(src, p, len) == 0
&& (vim_ispathsep(src[len])
|| (!one && (src[len] == ',' || src[len] == ' '))
|| src[len] == NUL)) {
@@ -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..158c22efaf 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;
}
@@ -821,10 +821,10 @@ int os_fchown(int fd, uv_uid_t owner, uv_gid_t group)
/// Check if a path exists.
///
/// @return `true` if `path` exists
-bool os_path_exists(const char_u *path)
+bool os_path_exists(const char *path)
{
uv_stat_t statbuf;
- return os_stat((char *)path, &statbuf) == kLibuvSuccess;
+ return os_stat(path, &statbuf) == kLibuvSuccess;
}
/// Sets file access and modification times.
@@ -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/input.c b/src/nvim/os/input.c
index bfe6d59dc6..ea9f31d776 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -293,7 +293,8 @@ static uint8_t check_multiclick(int code, int grid, int row, int col)
|| code == KE_MOUSEDOWN
|| code == KE_MOUSEUP
|| code == KE_MOUSELEFT
- || code == KE_MOUSERIGHT) {
+ || code == KE_MOUSERIGHT
+ || code == KE_MOUSEMOVE) {
return 0;
}
uint64_t mouse_time = os_hrtime(); // time of current mouse click (ns)
@@ -347,7 +348,8 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf, unsigned int bu
if (type != KS_EXTRA
|| !((mouse_code >= KE_LEFTMOUSE && mouse_code <= KE_RIGHTRELEASE)
- || (mouse_code >= KE_MOUSEDOWN && mouse_code <= KE_MOUSERIGHT))) {
+ || (mouse_code >= KE_MOUSEDOWN && mouse_code <= KE_MOUSERIGHT)
+ || mouse_code == KE_MOUSEMOVE)) {
return bufsize;
}
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index b793b8f9c6..cf66899493 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -52,11 +52,11 @@ static void save_patterns(int num_pat, char **pat, int *num_file, char ***file)
{
*file = xmalloc((size_t)num_pat * sizeof(char_u *));
for (int i = 0; i < num_pat; i++) {
- char_u *s = vim_strsave((char_u *)pat[i]);
+ char *s = xstrdup(pat[i]);
// Be compatible with expand_filename(): halve the number of
// backslashes.
backslash_halve(s);
- (*file)[i] = (char *)s;
+ (*file)[i] = s;
}
*num_file = num_pat;
}
@@ -64,7 +64,7 @@ static void save_patterns(int num_pat, char **pat, int *num_file, char ***file)
static bool have_wildcard(int num, char **file)
{
for (int i = 0; i < num; i++) {
- if (path_has_wildcard((char_u *)file[i])) {
+ if (path_has_wildcard(file[i])) {
return true;
}
}
@@ -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;
}
}
@@ -129,7 +129,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
bool is_fish_shell =
#if defined(UNIX)
- STRNCMP(invocation_path_tail(p_sh, NULL), "fish", 4) == 0;
+ STRNCMP(invocation_path_tail((char_u *)p_sh, NULL), "fish", 4) == 0;
#else
false;
#endif
@@ -160,7 +160,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
}
// get a name for the temp file
- if ((tempname = vim_tempname()) == NULL) {
+ if ((tempname = (char_u *)vim_tempname()) == NULL) {
emsg(_(e_notmp));
return FAIL;
}
@@ -182,14 +182,14 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
&& *(pat[0] + len - 1) == '`') {
shell_style = STYLE_BT;
} else if ((len = STRLEN(p_sh)) >= 3) {
- if (STRCMP(p_sh + len - 3, "csh") == 0) {
+ if (strcmp(p_sh + len - 3, "csh") == 0) {
shell_style = STYLE_GLOB;
- } else if (STRCMP(p_sh + len - 3, "zsh") == 0) {
+ } else if (strcmp(p_sh + len - 3, "zsh") == 0) {
shell_style = STYLE_PRINT;
}
}
if (shell_style == STYLE_ECHO
- && strstr(path_tail((char *)p_sh), "sh") != NULL) {
+ && strstr(path_tail(p_sh), "sh") != NULL) {
shell_style = STYLE_VIMGLOB;
}
@@ -503,12 +503,12 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
// Move the file names to allocated memory.
for (j = 0, i = 0; i < *num_file; i++) {
// Require the files to exist. Helps when using /bin/sh
- if (!(flags & EW_NOTFOUND) && !os_path_exists((char_u *)(*file)[i])) {
+ if (!(flags & EW_NOTFOUND) && !os_path_exists((*file)[i])) {
continue;
}
// 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;
}
@@ -555,11 +555,11 @@ notfound:
char **shell_build_argv(const char *cmd, const char *extra_args)
FUNC_ATTR_NONNULL_RET
{
- size_t argc = tokenize(p_sh, NULL) + (cmd ? tokenize(p_shcf, NULL) : 0);
+ size_t argc = tokenize((char_u *)p_sh, NULL) + (cmd ? tokenize(p_shcf, NULL) : 0);
char **rv = xmalloc((argc + 4) * sizeof(*rv));
// Split 'shell'
- size_t i = tokenize(p_sh, rv);
+ size_t i = tokenize((char_u *)p_sh, rv);
if (extra_args) {
rv[i++] = xstrdup(extra_args); // Push a copy of `extra_args`
@@ -700,7 +700,7 @@ int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg)
if (p_verbose > 3) {
verbose_enter();
- smsg(_("Executing command: \"%s\""), cmd == NULL ? p_sh : cmd);
+ smsg(_("Executing command: \"%s\""), cmd == NULL ? p_sh : (char *)cmd);
msg_putchar('\n');
verbose_leave();
}
@@ -746,7 +746,7 @@ char_u *get_cmd_output(char_u *cmd, char_u *infile, ShellOpts flags, size_t *ret
}
// get a name for the temp file
- char_u *tempname = vim_tempname();
+ char_u *tempname = (char_u *)vim_tempname();
if (tempname == NULL) {
emsg(_(e_notmp));
return NULL;
@@ -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--;
@@ -1106,13 +1106,13 @@ static void out_data_append_to_screen(char *output, size_t *count, bool eof)
// incomplete UTF-8 sequence that could be composing with the last
// complete sequence.
// This will be corrected when we switch to vterm based implementation
- int i = *p ? utfc_ptr2len_len((char_u *)p, (int)(end - p)) : 1;
+ int i = *p ? utfc_ptr2len_len(p, (int)(end - p)) : 1;
if (!eof && i == 1 && utf8len_tab_zero[*(uint8_t *)p] > (end - p)) {
*count = (size_t)(p - output);
goto end;
}
- (void)msg_outtrans_len_attr((char_u *)p, i, 0);
+ (void)msg_outtrans_len_attr(p, i, 0);
p += i;
}
}
@@ -1208,7 +1208,7 @@ static void read_input(DynamicBuffer *buf)
{
size_t written = 0, l = 0, len = 0;
linenr_T lnum = curbuf->b_op_start.lnum;
- char_u *lp = ml_get(lnum);
+ char_u *lp = (char_u *)ml_get(lnum);
for (;;) {
l = strlen((char *)lp + written);
@@ -1240,7 +1240,7 @@ static void read_input(DynamicBuffer *buf)
if (lnum > curbuf->b_op_end.lnum) {
break;
}
- lp = ml_get(lnum);
+ lp = (char_u *)ml_get(lnum);
written = 0;
} else if (len > 0) {
written += len;
@@ -1316,7 +1316,7 @@ static char *shell_xescape_xquote(const char *cmd)
}
const char *ecmd = cmd;
- if (*p_sxe != NUL && STRCMP(p_sxq, "(") == 0) {
+ if (*p_sxe != NUL && strcmp(p_sxq, "(") == 0) {
ecmd = (char *)vim_strsave_escaped_ext((char_u *)cmd, p_sxe, '^', false);
}
size_t ncmd_size = strlen(ecmd) + STRLEN(p_sxq) * 2 + 1;
@@ -1324,9 +1324,9 @@ static char *shell_xescape_xquote(const char *cmd)
// When 'shellxquote' is ( append ).
// When 'shellxquote' is "( append )".
- if (STRCMP(p_sxq, "(") == 0) {
+ if (strcmp(p_sxq, "(") == 0) {
vim_snprintf(ncmd, ncmd_size, "(%s)", ecmd);
- } else if (STRCMP(p_sxq, "\"(") == 0) {
+ } else if (strcmp(p_sxq, "\"(") == 0) {
vim_snprintf(ncmd, ncmd_size, "\"(%s)\"", ecmd);
} else {
vim_snprintf(ncmd, ncmd_size, "%s%s%s", p_sxq, ecmd, p_sxq);
diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c
index bd34e917b2..0c662e8843 100644
--- a/src/nvim/os/users.c
+++ b/src/nvim/os/users.c
@@ -93,7 +93,7 @@ int os_get_usernames(garray_T *users)
for (i = 0; i < users->ga_len; i++) {
char *local_user = ((char **)users->ga_data)[i];
- if (STRCMP(local_user, user_env) == 0) {
+ if (strcmp(local_user, user_env) == 0) {
break;
}
}
@@ -208,14 +208,14 @@ char *get_users(expand_T *xp, int idx)
/// @return 0 if name does not match any user name.
/// 1 if name partially matches the beginning of a user name.
/// 2 is name fully matches a user name.
-int match_user(char_u *name)
+int match_user(char *name)
{
int n = (int)STRLEN(name);
int result = 0;
init_users();
for (int i = 0; i < ga_users.ga_len; i++) {
- if (STRCMP(((char_u **)ga_users.ga_data)[i], name) == 0) {
+ if (strcmp(((char **)ga_users.ga_data)[i], name) == 0) {
return 2; // full match
}
if (STRNCMP(((char_u **)ga_users.ga_data)[i], name, n) == 0) {
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 1500254de5..ac07fbee87 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);
}
@@ -73,7 +73,7 @@ FileComparison path_full_compare(char *const s1, char *const s2, const bool chec
if (checkname) {
vim_FullName(exp1, full1, MAXPATHL, false);
vim_FullName(s2, full2, MAXPATHL, false);
- if (FNAMECMP(full1, full2) == 0) {
+ if (path_fnamecmp(full1, full2) == 0) {
return kEqualFileNames;
}
}
@@ -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
@@ -250,9 +248,7 @@ int vim_ispathsep(int c)
#endif
}
-/*
- * Like vim_ispathsep(c), but exclude the colon for MS-Windows.
- */
+// Like vim_ispathsep(c), but exclude the colon for MS-Windows.
int vim_ispathsep_nocolon(int c)
{
return vim_ispathsep(c)
@@ -262,9 +258,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 +308,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,13 +324,19 @@ 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;
}
/// Compare two file names
///
+/// On some systems case in a file name does not matter, on others it does.
+///
+/// @note Does not account for maximum name lengths and things like "../dir",
+/// thus it is not 100% accurate. OS may also use different algorithm for
+/// case-insensitive comparison.
+///
/// Handles '/' and '\\' correctly and deals with &fileignorecase option.
///
/// @param[in] fname1 First file name.
@@ -376,21 +374,21 @@ 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
if (p_fic) {
- return mb_strnicmp((const char_u *)fname1, (const char_u *)fname2, len);
+ return mb_strnicmp(fname1, fname2, len);
}
return strncmp(fname1, fname2, len);
#endif
@@ -515,7 +513,7 @@ char *save_abs_path(const char *name)
/// @param p The path to expand.
/// @returns Unix: True if it contains one of "?[{`'$".
/// @returns Windows: True if it contains one of "*?$[".
-bool path_has_wildcard(const char_u *p)
+bool path_has_wildcard(const char *p)
FUNC_ATTR_NONNULL_ALL
{
for (; *p; MB_PTR_ADV(p)) {
@@ -538,9 +536,7 @@ bool path_has_wildcard(const char_u *p)
return false;
}
-/*
- * Unix style wildcard expansion code.
- */
+// Unix style wildcard expansion code.
static int pstrcmp(const void *a, const void *b)
{
return pathcmp(*(char **)a, *(char **)b, -1);
@@ -585,7 +581,7 @@ bool path_has_exp_wildcard(const char_u *p)
static size_t path_expand(garray_T *gap, const char_u *path, int flags)
FUNC_ATTR_NONNULL_ALL
{
- return do_path_expand(gap, path, 0, flags, false);
+ return do_path_expand(gap, (char *)path, 0, flags, false);
}
static const char *scandir_next_with_dots(Directory *dir)
@@ -606,7 +602,7 @@ static const char *scandir_next_with_dots(Directory *dir)
/// Implementation of path_expand().
///
/// Chars before `path + wildoff` do not get expanded.
-static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff, int flags,
+static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, int flags,
bool didstar)
FUNC_ATTR_NONNULL_ALL
{
@@ -633,18 +629,18 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
char_u *p = buf;
char_u *s = buf;
char_u *e = NULL;
- const char_u *path_end = path;
+ const char_u *path_end = (char_u *)path;
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)) {
+ // 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 >= (char_u *)path + wildoff && rem_backslash((char *)path_end)) {
*p++ = *path_end++;
} else if (vim_ispathsep_nocolon(*path_end)) {
if (e != NULL) {
break;
}
s = p + 1;
- } else if (path_end >= path + wildoff
+ } else if (path_end >= (char_u *)path + wildoff
&& (vim_strchr("*?[{~$", *path_end) != NULL
#ifndef WIN32
|| (!p_fic && (flags & EW_ICASE) && mb_isalpha(utf_ptr2char((char *)path_end)))
@@ -661,10 +657,10 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
*e = NUL;
// 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)) {
+ // Remove backslashes between "wildoff" and the start of the wildcard
+ // component.
+ for (p = buf + wildoff; p < s; p++) {
+ if (rem_backslash((char *)p)) {
STRMOVE(p, p + 1);
e--;
s--;
@@ -672,7 +668,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;
}
@@ -708,13 +704,13 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
return 0;
}
- /* If "**" is by itself, this is the first time we encounter it and more
- * is following then find matches without any directory. */
+ // If "**" is by itself, this is the first time we encounter it and more
+ // is following then find matches without any directory.
if (!didstar && stardepth < 100 && starstar && e - s == 2
&& *path_end == '/') {
STRCPY(s, path_end + 1);
stardepth++;
- (void)do_path_expand(gap, buf, (size_t)(s - buf), flags, true);
+ (void)do_path_expand(gap, (char *)buf, (size_t)(s - buf), flags, true);
stardepth--;
}
*s = NUL;
@@ -723,27 +719,27 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
char *dirpath = (*buf == NUL ? "." : (char *)buf);
if (os_file_is_readable(dirpath) && os_scandir(&dir, dirpath)) {
// Find all matching entries.
- char_u *name;
+ char *name;
scandir_next_with_dots(NULL); // initialize
- while (!got_int && (name = (char_u *)scandir_next_with_dots(&dir)) != NULL) {
+ while (!got_int && (name = (char *)scandir_next_with_dots(&dir)) != NULL) {
if ((name[0] != '.'
|| starts_with_dot
|| ((flags & EW_DODOT)
&& name[1] != NUL
&& (name[1] != '.' || name[2] != NUL))) // -V557
- && ((regmatch.regprog != NULL && vim_regexec(&regmatch, (char *)name, 0))
+ && ((regmatch.regprog != NULL && vim_regexec(&regmatch, name, 0))
|| ((flags & EW_NOTWILD)
- && FNAMENCMP(path + (s - buf), name, e - s) == 0))) {
+ && path_fnamencmp(path + (s - buf), name, (size_t)(e - s)) == 0))) {
STRCPY(s, name);
len = STRLEN(buf);
if (starstar && stardepth < 100) {
- /* For "**" in the pattern first go deeper in the tree to
- * find matches. */
- STRCPY(buf + len, "/**");
+ // For "**" in the pattern first go deeper in the tree to
+ // find matches.
+ STRCPY(buf + len, "/**"); // NOLINT
STRCPY(buf + len + 3, path_end);
stardepth++;
- (void)do_path_expand(gap, buf, len + 1, flags, true);
+ (void)do_path_expand(gap, (char *)buf, len + 1, flags, true);
stardepth--;
}
@@ -751,18 +747,19 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
if (path_has_exp_wildcard(path_end)) { // handle more wildcards
// need to expand another component of the path
// remove backslashes for the remaining components only
- (void)do_path_expand(gap, buf, len + 1, flags, false);
+ (void)do_path_expand(gap, (char *)buf, len + 1, flags, false);
} else {
FileInfo file_info;
// 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)
- : os_path_exists(buf)) {
+ if ((flags & EW_ALLLINKS)
+ ? os_fileinfo_link((char *)buf, &file_info)
+ : os_path_exists((char *)buf)) {
addfile(gap, buf, flags);
}
}
@@ -784,10 +781,8 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff,
return matches;
}
-/*
- * Moves "*psep" back to the previous path separator in "path".
- * Returns FAIL is "*psep" ends up at the beginning of "path".
- */
+// Moves "*psep" back to the previous path separator in "path".
+// Returns FAIL is "*psep" ends up at the beginning of "path".
static int find_previous_pathsep(char_u *path, char_u **psep)
{
// skip the current separator
@@ -806,13 +801,11 @@ 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]".
- */
-static bool is_unique(char_u *maybe_unique, garray_T *gap, int 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 *maybe_unique, garray_T *gap, int i)
{
- char_u **other_paths = (char_u **)gap->ga_data;
+ char **other_paths = gap->ga_data;
for (int j = 0; j < gap->ga_len; j++) {
if (j == i) {
@@ -823,8 +816,8 @@ static bool is_unique(char_u *maybe_unique, garray_T *gap, int i)
if (other_path_len < candidate_len) {
continue; // it's different when it's shorter
}
- char_u *rival = other_paths[j] + other_path_len - candidate_len;
- if (FNAMECMP(maybe_unique, rival) == 0
+ char *rival = other_paths[j] + other_path_len - candidate_len;
+ if (path_fnamecmp(maybe_unique, rival) == 0
&& (rival == other_paths[j] || vim_ispathsep(*(rival - 1)))) {
return false; // match
}
@@ -832,27 +825,25 @@ static bool is_unique(char_u *maybe_unique, garray_T *gap, int i)
return true; // no match found
}
-/*
- * Split the 'path' option into an array of strings in garray_T. Relative
- * paths are expanded to their equivalent fullpath. This includes the "."
- * (relative to current buffer directory) and empty path (relative to current
- * directory) notations.
- *
- * TODO: handle upward search (;) and path limiter (**N) notations by
- * expanding each into their equivalent path(s).
- */
+// Split the 'path' option into an array of strings in garray_T. Relative
+// paths are expanded to their equivalent fullpath. This includes the "."
+// (relative to current buffer directory) and empty path (relative to current
+// directory) notations.
+//
+// TODO(vim): handle upward search (;) and path limiter (**N) notations by
+// expanding each into their equivalent path(s).
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 *buf = xmalloc(MAXPATHL);
+ char_u *path_option = *curbuf->b_p_path == NUL ? p_path : (char_u *)curbuf->b_p_path;
+ char *buf = xmalloc(MAXPATHL);
while (*path_option != NUL) {
- copy_option_part((char **)&path_option, (char *)buf, MAXPATHL, " ,");
+ copy_option_part((char **)&path_option, buf, MAXPATHL, " ,");
if (buf[0] == '.' && (buf[1] == NUL || vim_ispathsep(buf[1]))) {
- /* Relative to current buffer:
- * "/path/file" + "." -> "/path/"
- * "/path/file" + "./subdir" -> "/path/subdir" */
+ // Relative to current buffer:
+ // "/path/file" + "." -> "/path/"
+ // "/path/file" + "./subdir" -> "/path/subdir"
if (curbuf->b_ffname == NULL) {
continue;
}
@@ -867,12 +858,12 @@ static void expand_path_option(char_u *curdir, garray_T *gap)
STRMOVE(buf + len, buf + 2);
}
memmove(buf, curbuf->b_ffname, len);
- simplify_filename(buf);
+ simplify_filename((char_u *)buf);
} else if (buf[0] == NUL) {
STRCPY(buf, curdir); // relative to current directory
- } else if (path_with_url((char *)buf)) {
+ } else if (path_with_url(buf)) {
continue; // URL can't be used here
- } else if (!path_is_absolute(buf)) {
+ } else if (!path_is_absolute((char_u *)buf)) {
// Expand relative path to their full path equivalent
size_t len = STRLEN(curdir);
if (len + STRLEN(buf) + 3 > MAXPATHL) {
@@ -881,23 +872,21 @@ static void expand_path_option(char_u *curdir, garray_T *gap)
STRMOVE(buf + len + 1, buf);
STRCPY(buf, curdir);
buf[len] = (char_u)PATHSEP;
- simplify_filename(buf);
+ simplify_filename((char_u *)buf);
}
- GA_APPEND(char_u *, gap, vim_strsave(buf));
+ GA_APPEND(char *, gap, xstrdup(buf));
}
xfree(buf);
}
-/*
- * Returns a pointer to the file or directory name in "fname" that matches the
- * longest path in "ga"p, or NULL if there is no match. For example:
- *
- * path: /foo/bar/baz
- * fname: /foo/bar/baz/quux.txt
- * returns: ^this
- */
+// Returns a pointer to the file or directory name in "fname" that matches the
+// longest path in "ga"p, or NULL if there is no match. For example:
+//
+// path: /foo/bar/baz
+// fname: /foo/bar/baz/quux.txt
+// returns: ^this
static char_u *get_path_cutoff(char_u *fname, garray_T *gap)
{
int maxlen = 0;
@@ -931,19 +920,17 @@ static char_u *get_path_cutoff(char_u *fname, garray_T *gap)
return cutoff;
}
-/*
- * Sorts, removes duplicates and modifies all the fullpath names in "gap" so
- * that they are unique with respect to each other while conserving the part
- * that matches the pattern. Beware, this is at least O(n^2) wrt "gap->ga_len".
- */
+// Sorts, removes duplicates and modifies all the fullpath names in "gap" so
+// that they are unique with respect to each other while conserving the part
+// that matches the pattern. Beware, this is at least O(n^2) wrt "gap->ga_len".
static void uniquefy_paths(garray_T *gap, char_u *pattern)
{
- char_u **fnames = (char_u **)gap->ga_data;
+ char **fnames = gap->ga_data;
bool sort_again = false;
regmatch_T regmatch;
garray_T path_ga;
- char_u **in_curdir = NULL;
- char_u *short_name;
+ char **in_curdir = NULL;
+ char *short_name;
ga_remove_duplicate_strings(gap);
ga_init(&path_ga, (int)sizeof(char_u *), 1);
@@ -952,11 +939,11 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
// regex matches anywhere in the path. FIXME: is this valid for all
// possible patterns?
size_t len = STRLEN(pattern);
- char_u *file_pattern = xmalloc(len + 2);
+ char *file_pattern = xmalloc(len + 2);
file_pattern[0] = '*';
file_pattern[1] = NUL;
STRCAT(file_pattern, pattern);
- char *pat = file_pat_to_reg_pat((char *)file_pattern, NULL, NULL, true);
+ char *pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, true);
xfree(file_pattern);
if (pat == NULL) {
return;
@@ -969,28 +956,28 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
return;
}
- char_u *curdir = xmalloc(MAXPATHL);
- os_dirname(curdir, MAXPATHL);
- expand_path_option(curdir, &path_ga);
+ char *curdir = xmalloc(MAXPATHL);
+ os_dirname((char_u *)curdir, MAXPATHL);
+ expand_path_option((char_u *)curdir, &path_ga);
in_curdir = xcalloc((size_t)gap->ga_len, sizeof(char_u *));
for (int i = 0; i < gap->ga_len && !got_int; i++) {
- char_u *path = fnames[i];
+ char *path = fnames[i];
int is_in_curdir;
- char_u *dir_end = (char_u *)gettail_dir((const char *)path);
- char_u *pathsep_p;
- char_u *path_cutoff;
+ char *dir_end = (char *)gettail_dir((const char *)path);
+ char *pathsep_p;
+ char *path_cutoff;
len = STRLEN(path);
- is_in_curdir = FNAMENCMP(curdir, path, dir_end - path) == 0
+ is_in_curdir = path_fnamencmp(curdir, path, (size_t)(dir_end - path)) == 0
&& curdir[dir_end - path] == NUL;
if (is_in_curdir) {
- in_curdir[i] = vim_strsave(path);
+ in_curdir[i] = xstrdup(path);
}
// Shorten the filename while maintaining its uniqueness
- path_cutoff = get_path_cutoff(path, &path_ga);
+ path_cutoff = (char *)get_path_cutoff((char_u *)path, &path_ga);
// Don't assume all files can be reached without path when search
// pattern starts with **/, so only remove path_cutoff
@@ -998,7 +985,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
if (pattern[0] == '*' && pattern[1] == '*'
&& vim_ispathsep_nocolon(pattern[2])
&& path_cutoff != NULL
- && vim_regexec(&regmatch, (char *)path_cutoff, (colnr_T)0)
+ && vim_regexec(&regmatch, path_cutoff, (colnr_T)0)
&& is_unique(path_cutoff, gap, i)) {
sort_again = true;
memmove(path, path_cutoff, STRLEN(path_cutoff) + 1);
@@ -1006,8 +993,8 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
// Here all files can be reached without path, so get shortest
// unique path. We start at the end of the path. */
pathsep_p = path + len - 1;
- while (find_previous_pathsep(path, &pathsep_p)) {
- if (vim_regexec(&regmatch, (char *)pathsep_p + 1, (colnr_T)0)
+ while (find_previous_pathsep((char_u *)path, (char_u **)&pathsep_p)) {
+ if (vim_regexec(&regmatch, pathsep_p + 1, (colnr_T)0)
&& is_unique(pathsep_p + 1, gap, i)
&& path_cutoff != NULL && pathsep_p + 1 >= path_cutoff) {
sort_again = true;
@@ -1017,7 +1004,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
}
}
- if (path_is_absolute(path)) {
+ if (path_is_absolute((char_u *)path)) {
// Last resort: shorten relative to curdir if possible.
// 'possible' means:
// 1. It is under the current directory.
@@ -1031,7 +1018,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
short_name = path_shorten_fname(path, curdir);
if (short_name != NULL && short_name > path + 1) {
STRCPY(path, ".");
- add_pathsep((char *)path);
+ add_pathsep(path);
STRMOVE(path + STRLEN(path), short_name);
}
}
@@ -1040,15 +1027,15 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
// Shorten filenames in /in/current/directory/{filename}
for (int i = 0; i < gap->ga_len && !got_int; i++) {
- char_u *rel_path;
- char_u *path = in_curdir[i];
+ char *rel_path;
+ char *path = in_curdir[i];
if (path == NULL) {
continue;
}
- /* If the {filename} is not unique, change it to ./{filename}.
- * Else reduce it to {filename} */
+ // If the {filename} is not unique, change it to ./{filename}.
+ // Else reduce it to {filename}
short_name = path_shorten_fname(path, curdir);
if (short_name == NULL) {
short_name = path;
@@ -1060,7 +1047,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
rel_path = xmalloc(STRLEN(short_name) + STRLEN(PATHSEPSTR) + 2);
STRCPY(rel_path, ".");
- add_pathsep((char *)rel_path);
+ add_pathsep(rel_path);
STRCAT(rel_path, short_name);
xfree(fnames[i]);
@@ -1143,16 +1130,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 +1152,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)
{
@@ -1221,26 +1206,23 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
int add_pat;
bool did_expand_in_path = false;
- /*
- * expand_env() is called to expand things like "~user". If this fails,
- * it calls ExpandOne(), which brings us back here. In this case, always
- * call the machine specific expansion function, if possible. Otherwise,
- * return FAIL.
- */
- if (recursive)
+ // expand_env() is called to expand things like "~user". If this fails,
+ // it calls ExpandOne(), which brings us back here. In this case, always
+ // call the machine specific expansion function, if possible. Otherwise,
+ // return FAIL.
+ if (recursive) {
#ifdef SPECIAL_WILDCHAR
- { return os_expand_wildcards(num_pat, pat, num_file, file, flags); }
+ return os_expand_wildcards(num_pat, pat, num_file, file, flags);
#else
- { return FAIL; }
+ return FAIL;
#endif
+ }
#ifdef SPECIAL_WILDCHAR
- /*
- * If there are any special wildcard characters which we cannot handle
- * here, call machine specific function for all the expansion. This
- * avoids starting the shell for each argument separately.
- * For `=expr` do use the internal function.
- */
+ // If there are any special wildcard characters which we cannot handle
+ // here, call machine specific function for all the expansion. This
+ // avoids starting the shell for each argument separately.
+ // For `=expr` do use the internal function.
for (int i = 0; i < num_pat; i++) {
if (has_special_wildchar((char_u *)pat[i])
&& !(vim_backtick((char_u *)pat[i]) && pat[i][1] == '=')) {
@@ -1251,9 +1233,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
recursive = true;
- /*
- * The matching file names are stored in a growarray. Init it empty.
- */
+ // The matching file names are stored in a growarray. Init it empty.
ga_init(&ga, (int)sizeof(char_u *), 30);
for (int i = 0; i < num_pat && !got_int; i++) {
@@ -1261,7 +1241,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
p = (char_u *)pat[i];
if (vim_backtick(p)) {
- add_pat = expand_backtick(&ga, p, flags);
+ add_pat = expand_backtick(&ga, (char *)p, flags);
if (add_pat == -1) {
recursive = false;
FreeWild(ga.ga_len, ga.ga_data);
@@ -1275,40 +1255,37 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
p = expand_env_save_opt(p, true);
if (p == NULL) {
p = (char_u *)pat[i];
- }
+ } else {
#ifdef UNIX
- /*
- * On Unix, if expand_env() can't expand an environment
- * variable, use the shell to do that. Discard previously
- * found file names and start all over again.
- */
- else if (has_env_var(p) || *p == '~') {
- xfree(p);
- ga_clear_strings(&ga);
- i = os_expand_wildcards(num_pat, pat, num_file, file,
- flags | EW_KEEPDOLLAR);
- recursive = false;
- return i;
- }
+ // On Unix, if expand_env() can't expand an environment
+ // variable, use the shell to do that. Discard previously
+ // found file names and start all over again.
+ if (has_env_var(p) || *p == '~') {
+ xfree(p);
+ ga_clear_strings(&ga);
+ i = os_expand_wildcards(num_pat, pat, num_file, file,
+ flags | EW_KEEPDOLLAR);
+ recursive = false;
+ return i;
+ }
#endif
+ }
}
- /*
- * If there are wildcards: Expand file names and add each match to
- * the list. If there is no match, and EW_NOTFOUND is given, add
- * the pattern.
- * If there are no wildcards: Add the file name if it exists or
- * when EW_NOTFOUND is given.
- */
- if (path_has_exp_wildcard(p)) {
+ // If there are wildcards or case-insensitive expansion is
+ // required: Expand file names and add each match to the list. If
+ // there is no match, and EW_NOTFOUND is given, add the pattern.
+ // Otherwise: Add the file name if it exists or when EW_NOTFOUND is
+ // given.
+ if (path_has_exp_wildcard(p) || (flags & EW_ICASE)) {
if ((flags & EW_PATH)
&& !path_is_absolute(p)
&& !(p[0] == '.'
&& (vim_ispathsep(p[1])
|| (p[1] == '.'
&& vim_ispathsep(p[2]))))) {
- /* :find completion where 'path' is used.
- * Recursiveness is OK here. */
+ // :find completion where 'path' is used.
+ // Recursiveness is OK here.
recursive = false;
add_pat = expand_in_path(&ga, p, flags);
recursive = true;
@@ -1322,10 +1299,10 @@ 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. */
+ // When EW_NOTFOUND is used, always add files and dirs. Makes
+ // "vim c:/" work.
if (flags & EW_NOTFOUND) {
addfile(&ga, t, flags | EW_DIR | EW_FILE);
} else {
@@ -1365,9 +1342,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) == '`';
@@ -1378,14 +1353,14 @@ static int vim_backtick(char_u *p)
/// Returns number of file names found, -1 if an error is encountered.
///
/// @param flags EW_* flags
-static int expand_backtick(garray_T *gap, char_u *pat, int flags)
+static int expand_backtick(garray_T *gap, char *pat, int flags)
{
char *p;
char *buffer;
int cnt = 0;
// Create the command: lop off the backticks.
- char *cmd = (char *)vim_strnsave(pat + 1, STRLEN(pat) - 2);
+ char *cmd = xstrnsave(pat + 1, STRLEN(pat) - 2);
if (*cmd == '=') { // `={expr}`: Expand expression
buffer = eval_to_string(cmd + 1, &p, true);
@@ -1473,7 +1448,7 @@ void addfile(garray_T *gap, char_u *f, int flags)
if (!(flags & EW_NOTFOUND)
&& ((flags & EW_ALLLINKS)
? !os_fileinfo_link((char *)f, &file_info)
- : !os_path_exists(f))) {
+ : !os_path_exists((char *)f))) {
return;
}
@@ -1484,7 +1459,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;
}
@@ -1502,21 +1477,17 @@ void addfile(garray_T *gap, char_u *f, int flags)
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(p);
#endif
- /*
- * Append a slash or backslash after directory names if none is present.
- */
+ // Append a slash or backslash after directory names if none is present.
if (isdir && (flags & EW_ADDSLASH)) {
add_pathsep((char *)p);
}
GA_APPEND(char_u *, gap, p);
}
-/*
- * Converts a file name into a canonical form. It simplifies a file name into
- * its simplest form by stripping out unneeded components, if any. The
- * resulting file name is simplified in place and will either be the same
- * length as that supplied, or shorter.
- */
+// Converts a file name into a canonical form. It simplifies a file name into
+// its simplest form by stripping out unneeded components, if any. The
+// resulting file name is simplified in place and will either be the same
+// length as that supplied, or shorter.
void simplify_filename(char_u *filename)
{
int components = 0;
@@ -1540,8 +1511,8 @@ void simplify_filename(char_u *filename)
start = p; // remember start after "c:/" or "/" or "///"
do {
- /* At this point "p" is pointing to the char following a single "/"
- * or "p" is at the "start" of the (absolute or relative) path name. */
+ // At this point "p" is pointing to the char following a single "/"
+ // or "p" is at the "start" of the (absolute or relative) path name.
if (vim_ispathsep(*p)) {
STRMOVE(p, p + 1); // remove duplicate "/"
} else if (p[0] == '.'
@@ -1549,10 +1520,10 @@ void simplify_filename(char_u *filename)
if (p == start && relative) {
p += 1 + (p[1] != NUL); // keep single "." or leading "./"
} else {
- /* Strip "./" or ".///". If we are at the end of the file name
- * and there is no trailing path separator, either strip "/." if
- * we are after "start", or strip "." if we are at the beginning
- * of an absolute path name . */
+ // Strip "./" or ".///". If we are at the end of the file name
+ // and there is no trailing path separator, either strip "/." if
+ // we are after "start", or strip "." if we are at the beginning
+ // of an absolute path name.
tail = p + 1;
if (p[1] != NUL) {
while (vim_ispathsep(*tail)) {
@@ -1577,9 +1548,9 @@ void simplify_filename(char_u *filename)
// Don't strip for an erroneous file name.
if (!stripping_disabled) {
- /* If the preceding component does not exist in the file
- * system, we strip it. On Unix, we don't accept a symbolic
- * link that refers to a non-existent file. */
+ // If the preceding component does not exist in the file
+ // system, we strip it. On Unix, we don't accept a symbolic
+ // link that refers to a non-existent file.
saved_char = p[-1];
p[-1] = NUL;
FileInfo file_info;
@@ -1595,16 +1566,16 @@ void simplify_filename(char_u *filename)
}
if (!do_strip) {
- /* If the component exists in the file system, check
- * that stripping it won't change the meaning of the
- * file name. First get information about the
- * unstripped file name. This may fail if the component
- * to strip is not a searchable directory (but a regular
- * file, for instance), since the trailing "/.." cannot
- * be applied then. We don't strip it then since we
- * don't want to replace an erroneous file name by
- * a valid one, and we disable stripping of later
- * components. */
+ // If the component exists in the file system, check
+ // that stripping it won't change the meaning of the
+ // file name. First get information about the
+ // unstripped file name. This may fail if the component
+ // to strip is not a searchable directory (but a regular
+ // file, for instance), since the trailing "/.." cannot
+ // be applied then. We don't strip it then since we
+ // don't want to replace an erroneous file name by
+ // a valid one, and we disable stripping of later
+ // components.
saved_char = *tail;
*tail = NUL;
if (os_fileinfo((char *)filename, &file_info)) {
@@ -1614,13 +1585,13 @@ void simplify_filename(char_u *filename)
}
*tail = saved_char;
if (do_strip) {
- /* The check for the unstripped file name
- * above works also for a symbolic link pointing to
- * a searchable directory. But then the parent of
- * the directory pointed to by the link must be the
- * same as the stripped file name. (The latter
- * exists in the file system since it is the
- * component's parent directory.) */
+ // The check for the unstripped file name
+ // above works also for a symbolic link pointing to
+ // a searchable directory. But then the parent of
+ // the directory pointed to by the link must be the
+ // same as the stripped file name. (The latter
+ // exists in the file system since it is the
+ // component's parent directory.)
FileInfo new_file_info;
if (p == start && relative) {
os_fileinfo(".", &new_file_info);
@@ -1633,26 +1604,26 @@ void simplify_filename(char_u *filename)
if (!os_fileinfo_id_equal(&file_info, &new_file_info)) {
do_strip = false;
- /* We don't disable stripping of later
- * components since the unstripped path name is
- * still valid. */
+ // We don't disable stripping of later
+ // components since the unstripped path name is
+ // still valid.
}
}
}
}
if (!do_strip) {
- /* Skip the ".." or "../" and reset the counter for the
- * components that might be stripped later on. */
+ // Skip the ".." or "../" and reset the counter for the
+ // components that might be stripped later on.
p = tail;
components = 0;
} else {
- /* Strip previous component. If the result would get empty
- * and there is no trailing path separator, leave a single
- * "." instead. If we are at the end of the file name and
- * there is no trailing path separator and a preceding
- * component is left after stripping, strip its trailing
- * path separator as well. */
+ // Strip previous component. If the result would get empty
+ // and there is no trailing path separator, leave a single
+ // "." instead. If we are at the end of the file name and
+ // there is no trailing path separator and a preceding
+ // component is left after stripping, strip its trailing
+ // path separator as well.
if (p == start && relative && tail[-1] == '.') {
*p++ = '.';
*p = NUL;
@@ -1684,7 +1655,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;
@@ -1694,17 +1665,17 @@ static char *eval_includeexpr(const char *const ptr, const size_t len)
/// Otherwise like file_name_at_cursor().
///
/// @param rel_fname file we are searching relative to
-char_u *find_file_name_in_path(char_u *ptr, size_t len, int options, long count, char_u *rel_fname)
+char *find_file_name_in_path(char *ptr, size_t len, int options, long count, char *rel_fname)
{
- char_u *file_name;
- char_u *tofree = NULL;
+ char *file_name;
+ char *tofree = NULL;
if (len == 0) {
return NULL;
}
if ((options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
- tofree = (char_u *)eval_includeexpr((char *)ptr, len);
+ tofree = eval_includeexpr(ptr, len);
if (tofree != NULL) {
ptr = tofree;
len = STRLEN(ptr);
@@ -1712,38 +1683,37 @@ char_u *find_file_name_in_path(char_u *ptr, size_t len, int options, long count,
}
if (options & FNAME_EXP) {
- file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS, true,
- rel_fname);
+ file_name = (char *)find_file_in_path((char_u *)ptr, len, options & ~FNAME_MESS, true,
+ (char_u *)rel_fname);
- /*
- * If the file could not be found in a normal way, try applying
- * 'includeexpr' (unless done already).
- */
+ // If the file could not be found in a normal way, try applying
+ // 'includeexpr' (unless done already).
if (file_name == NULL
&& !(options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
- tofree = (char_u *)eval_includeexpr((char *)ptr, len);
+ tofree = eval_includeexpr(ptr, len);
if (tofree != NULL) {
ptr = tofree;
len = STRLEN(ptr);
- file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
- TRUE, rel_fname);
+ file_name = (char *)find_file_in_path((char_u *)ptr, len, options & ~FNAME_MESS,
+ true, (char_u *)rel_fname);
}
}
if (file_name == NULL && (options & FNAME_MESS)) {
- char_u c = ptr[len];
+ char c = ptr[len];
ptr[len] = NUL;
semsg(_("E447: Can't find file \"%s\" in path"), ptr);
ptr[len] = c;
}
- /* Repeat finding the file "count" times. This matters when it
- * appears several times in the path. */
+ // Repeat finding the file "count" times. This matters when it
+ // 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 =
+ (char *)find_file_in_path((char_u *)ptr, len, options, false, (char_u *)rel_fname);
}
} else {
- file_name = vim_strnsave(ptr, len);
+ file_name = xstrnsave(ptr, len);
}
xfree(tofree);
@@ -1751,12 +1721,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 +1765,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 +1777,7 @@ int path_with_url(const char *fname)
return 0;
}
- // "://" or ":\\" must follow
+ // ":/" or ":\\" must follow
return path_is_url(p);
}
@@ -1802,9 +1790,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 +1827,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 +1886,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;
@@ -1922,7 +1908,7 @@ void path_fix_case(char *name)
while ((entry = (char *)os_scandir_next(&dir))) {
// Only accept names that differ in case and are the same byte
// length. TODO: accept different length name.
- if (STRICMP(tail, entry) == 0 && STRLEN(tail) == STRLEN(entry)) {
+ if (STRICMP(tail, entry) == 0 && strlen(tail) == strlen(entry)) {
char_u newname[MAXPATHL + 1];
// Verify the inode is equal.
@@ -1941,21 +1927,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;
+ && utf_head_off(b, 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,18 +1949,16 @@ 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
&& pathcmp((char *)ffname, (char *)f2, (int)(t1 - ffname)) == 0;
}
-/*
- * Compare path "p[]" to "q[]".
- * If "maxlen" >= 0 compare "p[maxlen]" to "q[maxlen]"
- * Return value like strcmp(p, q), but consider path separators.
- */
+// Compare path "p[]" to "q[]".
+// If "maxlen" >= 0 compare "p[maxlen]" to "q[maxlen]"
+// Return value like strcmp(p, q), but consider path separators.
int pathcmp(const char *p, const char *q, int maxlen)
{
int i, j;
@@ -2063,7 +2043,7 @@ char_u *path_try_shorten_fname(char_u *full_path)
char_u *p = full_path;
if (os_dirname(dirname, MAXPATHL) == OK) {
- p = path_shorten_fname(full_path, dirname);
+ p = (char_u *)path_shorten_fname((char *)full_path, (char *)dirname);
if (p == NULL || *p == NUL) {
p = full_path;
}
@@ -2079,7 +2059,7 @@ char_u *path_try_shorten_fname(char_u *full_path)
/// @return
/// - Pointer into `full_path` if shortened.
/// - NULL if no shorter name is possible.
-char_u *path_shorten_fname(char_u *full_path, char_u *dir_name)
+char *path_shorten_fname(char *full_path, char *dir_name)
{
if (full_path == NULL) {
return NULL;
@@ -2089,17 +2069,17 @@ char_u *path_shorten_fname(char_u *full_path, char_u *dir_name)
size_t len = STRLEN(dir_name);
// If dir_name is a path head, full_path can always be made relative.
- if (len == (size_t)path_head_length() && is_path_head(dir_name)) {
+ if (len == (size_t)path_head_length() && is_path_head((char_u *)dir_name)) {
return full_path + len;
}
// If full_path and dir_name do not match, it's impossible to make one
// relative to the other.
- if (FNAMENCMP(dir_name, full_path, len) != 0) {
+ if (path_fnamencmp(dir_name, full_path, len) != 0) {
return NULL;
}
- char_u *p = full_path + len;
+ char_u *p = (char_u *)full_path + len;
// If *p is not pointing to a path separator, this means that full_path's
// last directory name is longer than *dir_name's last directory, so they
@@ -2108,7 +2088,7 @@ char_u *path_shorten_fname(char_u *full_path, char_u *dir_name)
return NULL;
}
- return p + 1;
+ return (char *)p + 1;
}
/// Invoke expand_wildcards() for one pattern
@@ -2125,20 +2105,25 @@ char_u *path_shorten_fname(char_u *full_path, char_u *dir_name)
/// If FAIL is returned, *num_file and *file are either
/// unchanged or *num_file is set to 0 and *file is set
/// to NULL or points to "".
-int expand_wildcards_eval(char_u **pat, int *num_file, char ***file, int flags)
+int expand_wildcards_eval(char **pat, int *num_file, char ***file, int flags)
{
int ret = FAIL;
- char_u *eval_pat = NULL;
- char *exp_pat = (char *)(*pat);
+ char *eval_pat = NULL;
+ char *exp_pat = *pat;
char *ignored_msg;
size_t usedlen;
+ const bool is_cur_alt_file = *exp_pat == '%' || *exp_pat == '#';
+ bool star_follows = false;
- if (*exp_pat == '%' || *exp_pat == '#' || *exp_pat == '<') {
+ if (is_cur_alt_file || *exp_pat == '<') {
emsg_off++;
- eval_pat = eval_vars((char_u *)exp_pat, (char_u *)exp_pat, &usedlen, NULL, &ignored_msg, NULL);
+ eval_pat = (char *)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);
+ star_follows = strcmp(exp_pat + usedlen, "*") == 0;
+ exp_pat = concat_str(eval_pat, exp_pat + usedlen);
}
}
@@ -2147,6 +2132,16 @@ int expand_wildcards_eval(char_u **pat, int *num_file, char ***file, int flags)
}
if (eval_pat != NULL) {
+ if (*num_file == 0 && is_cur_alt_file && star_follows) {
+ // Expanding "%" or "#" and the file does not exist: Add the
+ // pattern anyway (without the star) so that this works for remote
+ // files and non-file buffer names.
+ *file = xmalloc(sizeof(char *));
+ **file = eval_pat;
+ eval_pat = NULL;
+ *num_file = 1;
+ ret = OK;
+ }
xfree(exp_pat);
xfree(eval_pat);
}
@@ -2182,9 +2177,7 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
return retval;
}
- /*
- * Remove names that match 'wildignore'.
- */
+ // Remove names that match 'wildignore'.
if (*p_wig) {
char_u *ffname;
@@ -2194,7 +2187,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++) {
@@ -2213,7 +2206,7 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
if (*num_files > 1 && !got_int) {
non_suf_match = 0;
for (i = 0; i < *num_files; i++) {
- if (!match_suffix((char_u *)(*files)[i])) {
+ if (!match_suffix((*files)[i])) {
// Move the name without matching suffix to the front of the list.
p = (char_u *)(*files)[i];
for (j = i; j > non_suf_match; j--) {
@@ -2233,29 +2226,27 @@ 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'.
- */
-int match_suffix(char_u *fname)
+/// @return true if "fname" matches with an entry in 'suffixes'.
+int match_suffix(char *fname)
{
#define MAXSUFLEN 30 // maximum length of a file suffix
- char_u suf_buf[MAXSUFLEN];
+ char suf_buf[MAXSUFLEN];
size_t fnamelen = STRLEN(fname);
size_t setsuflen = 0;
for (char_u *setsuf = p_su; *setsuf;) {
setsuflen = copy_option_part((char **)&setsuf, (char *)suf_buf, MAXSUFLEN, ".,");
if (setsuflen == 0) {
- char_u *tail = (char_u *)path_tail((char *)fname);
+ char *tail = path_tail(fname);
// empty entry: match name without a '.'
- if (vim_strchr((char *)tail, '.') == NULL) {
+ if (vim_strchr(tail, '.') == NULL) {
setsuflen = 1;
break;
}
} else {
if (fnamelen >= setsuflen
- && FNAMENCMP(suf_buf, fname + fnamelen - setsuflen, setsuflen) == 0) {
+ && path_fnamencmp(suf_buf, fname + fnamelen - setsuflen, setsuflen) == 0) {
break;
}
setsuflen = 0;
@@ -2273,7 +2264,7 @@ int path_full_dir_name(char *directory, char *buffer, size_t len)
int SUCCESS = 0;
int retval = OK;
- if (STRLEN(directory) == 0) {
+ if (strlen(directory) == 0) {
return os_dirname((char_u *)buffer, len);
}
@@ -2354,20 +2345,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 +2372,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
@@ -2449,8 +2440,8 @@ void path_guess_exepath(const char *argv0, char *buf, size_t bufsize)
continue;
}
STRLCPY(NameBuff, dir, dir_len + 1);
- STRLCAT(NameBuff, PATHSEPSTR, sizeof(NameBuff));
- STRLCAT(NameBuff, argv0, sizeof(NameBuff));
+ xstrlcat(NameBuff, PATHSEPSTR, sizeof(NameBuff));
+ xstrlcat(NameBuff, argv0, sizeof(NameBuff));
if (os_can_exe((char *)NameBuff, NULL, false)) {
xstrlcpy(buf, (char *)NameBuff, bufsize);
return;
diff --git a/src/nvim/path.h b/src/nvim/path.h
index 1006ef9ffb..37a0883c7f 100644
--- a/src/nvim/path.h
+++ b/src/nvim/path.h
@@ -18,8 +18,8 @@
#define EW_NOERROR 0x200 // no error for bad regexp
#define EW_NOTWILD 0x400 // add match with literal name if exists
#define EW_KEEPDOLLAR 0x800 // do not escape $, $var is expanded
-/* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND
-* is used when executing commands and EW_SILENT for interactive expanding. */
+// Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND
+// is used when executing commands and EW_SILENT for interactive expanding.
#define EW_ALLLINKS 0x1000 // also links not pointing to existing file
#define EW_SHELLCMD 0x2000 // called from expand_shellcmd(), don't check
// if executable is in $PATH
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index 70bdbd8b1d..cbde0cfff9 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -98,7 +98,7 @@ 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;
@@ -106,7 +106,7 @@ int plines_win_nofold(win_T *wp, linenr_T lnum)
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.
@@ -144,24 +144,28 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column)
return lines + 1;
}
- char_u *line = ml_get_buf(wp->w_buffer, lnum, false);
- char_u *s = line;
+ char_u *line = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
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, (char *)line, (char *)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, s, 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,38 @@ 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, (char *)line, (char *)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 FUNC_ATTR_UNUSED,
+ colnr_T col, char *line, char *ptr)
+{
+ cts->cts_win = wp;
+ cts->cts_vcol = col;
+ cts->cts_line = line;
+ cts->cts_ptr = 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 +311,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 +330,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 +345,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 +365,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 +397,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 +415,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 +441,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 +491,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 +517,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 +529,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..f463d82f10 100644
--- a/src/nvim/plines.h
+++ b/src/nvim/plines.h
@@ -3,6 +3,19 @@
#include "nvim/vim.h"
+// Argument for lbr_chartabsize().
+typedef struct {
+ win_T *cts_win;
+ 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 dfcc052288..f4d39327b3 100644
--- a/src/nvim/po/da.po
+++ b/src/nvim/po/da.po
@@ -4142,7 +4142,7 @@ msgid "freeing %ld lines"
msgstr "frigør %ld linjer"
#, c-format
-msgid " into \"%c"
+msgid " into \"%s"
msgstr " i \"%c"
#, c-format
@@ -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 614ba013e6..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"
@@ -4410,7 +4410,7 @@ msgid "freeing %ld lines"
msgstr "libration de %ld lignes"
#, c-format
-msgid " into \"%c"
+msgid " into \"%s"
msgstr " dans \"%c"
#, c-format
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 fae2fd4967..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ı"
@@ -4149,7 +4149,7 @@ msgid "E748: No previously used register"
msgstr "E748: Daha önce kullanılan bir yazmaç yok"
#, c-format
-msgid " into \"%c"
+msgid " into \"%s"
msgstr " \"%c"
#, c-format
diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po
index da87d50683..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: Забагато груп підсвічування і синтаксису"
@@ -4132,7 +4132,7 @@ msgid "E748: No previously used register"
msgstr "E748: Регістри перед цим не вживались"
#, c-format
-msgid " into \"%c"
+msgid " into \"%s"
msgstr " у \"%c"
#, c-format
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..4de3713f4f 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
@@ -1047,6 +1045,10 @@ void pum_show_popupmenu(vimmenu_T *menu)
pum_selected = -1;
pum_first = 0;
+ if (!p_mousemev) {
+ // Pretend 'mousemoveevent' is set.
+ ui_call_option_set(STATIC_CSTR_AS_STRING("mousemoveevent"), BOOLEAN_OBJ(true));
+ }
for (;;) {
pum_is_visible = true;
@@ -1104,6 +1106,9 @@ void pum_show_popupmenu(vimmenu_T *menu)
xfree(array);
pum_undisplay(true);
+ if (!p_mousemev) {
+ ui_call_option_set(STATIC_CSTR_AS_STRING("mousemoveevent"), BOOLEAN_OBJ(false));
+ }
}
void pum_make_popup(const char *path_name, int use_mouse_pos)
diff --git a/src/nvim/profile.c b/src/nvim/profile.c
index d4f3756f4d..50a8a371f5 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);
@@ -291,23 +291,23 @@ void ex_profile(exarg_T *eap)
set_vim_var_nr(VV_PROFILING, 1L);
} else if (do_profiling == PROF_NONE) {
emsg(_("E750: First use \":profile start {fname}\""));
- } else if (STRCMP(eap->arg, "stop") == 0) {
+ } else if (strcmp(eap->arg, "stop") == 0) {
profile_dump();
do_profiling = PROF_NONE;
set_vim_var_nr(VV_PROFILING, 0L);
profile_reset();
- } else if (STRCMP(eap->arg, "pause") == 0) {
+ } else if (strcmp(eap->arg, "pause") == 0) {
if (do_profiling == PROF_YES) {
pause_time = profile_start();
}
do_profiling = PROF_PAUSED;
- } else if (STRCMP(eap->arg, "continue") == 0) {
+ } else if (strcmp(eap->arg, "continue") == 0) {
if (do_profiling == PROF_PAUSED) {
pause_time = profile_end(pause_time);
profile_set_wait(profile_add(profile_get_wait(), pause_time));
}
do_profiling = PROF_YES;
- } else if (STRCMP(eap->arg, "dump") == 0) {
+ } else if (strcmp(eap->arg, "dump") == 0) {
profile_dump();
} else {
// The rest is similar to ":breakadd".
@@ -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,14 +721,14 @@ 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 {
// Keep going till the end of file, so that trailing
// continuation lines are listed.
for (int i = 0;; i++) {
- if (vim_fgets(IObuff, IOSIZE, sfd)) {
+ if (vim_fgets((char_u *)IObuff, IOSIZE, sfd)) {
break;
}
// When a line has been truncated, append NL, taking care
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 17fbbe17b8..9494308ef0 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
@@ -710,7 +710,7 @@ static int qf_get_next_buf_line(qfstate_T *state)
if (state->buflnum > state->lnumlast) {
return QF_END_OF_INPUT;
}
- char *p_buf = (char *)ml_get_buf(state->buf, state->buflnum, false);
+ char *p_buf = ml_get_buf(state->buf, state->buflnum, false);
state->buflnum += 1;
size_t len = STRLEN(p_buf);
@@ -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,14 +1091,14 @@ 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;
}
// If the errorformat didn't change between calls, then reuse the previously
// parsed values.
- if (last_efm == NULL || (STRCMP(last_efm, efm) != 0)) {
+ if (last_efm == NULL || (strcmp(last_efm, efm) != 0)) {
// free the previously parsed data
XFREE_CLEAR(last_efm);
free_efm_list(&fmt_first);
@@ -1242,15 +1242,15 @@ 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]);
+ char c = *rmp->endp[midx];
*rmp->endp[midx] = NUL;
- expand_env(rmp->startp[midx], (char_u *)fields->namebuf, CMDBUFFSIZE);
- *rmp->endp[midx] = (char_u)c;
+ expand_env(rmp->startp[midx], fields->namebuf, CMDBUFFSIZE);
+ *rmp->endp[midx] = c;
// For separate filename patterns (%O, %P and %Q), the specified file
// should exist.
if (vim_strchr("OPQ", prefix) != NULL
- && !os_path_exists((char_u *)fields->namebuf)) {
+ && !os_path_exists(fields->namebuf)) {
return QF_FAIL;
}
@@ -1264,7 +1264,7 @@ static int qf_parse_fmt_n(regmatch_T *rmp, int midx, qffields_T *fields)
if (rmp->startp[midx] == NULL) {
return QF_FAIL;
}
- fields->enr = (int)atol((char *)rmp->startp[midx]);
+ fields->enr = (int)atol(rmp->startp[midx]);
return QF_OK;
}
@@ -1275,7 +1275,7 @@ static int qf_parse_fmt_l(regmatch_T *rmp, int midx, qffields_T *fields)
if (rmp->startp[midx] == NULL) {
return QF_FAIL;
}
- fields->lnum = (linenr_T)atol((char *)rmp->startp[midx]);
+ fields->lnum = (linenr_T)atol(rmp->startp[midx]);
return QF_OK;
}
@@ -1286,7 +1286,7 @@ static int qf_parse_fmt_e(regmatch_T *rmp, int midx, qffields_T *fields)
if (rmp->startp[midx] == NULL) {
return QF_FAIL;
}
- fields->end_lnum = (linenr_T)atol((char *)rmp->startp[midx]);
+ fields->end_lnum = (linenr_T)atol(rmp->startp[midx]);
return QF_OK;
}
@@ -1297,7 +1297,7 @@ static int qf_parse_fmt_c(regmatch_T *rmp, int midx, qffields_T *fields)
if (rmp->startp[midx] == NULL) {
return QF_FAIL;
}
- fields->col = (int)atol((char *)rmp->startp[midx]);
+ fields->col = (int)atol(rmp->startp[midx]);
return QF_OK;
}
@@ -1308,7 +1308,7 @@ static int qf_parse_fmt_k(regmatch_T *rmp, int midx, qffields_T *fields)
if (rmp->startp[midx] == NULL) {
return QF_FAIL;
}
- fields->end_col = (int)atol((char *)rmp->startp[midx]);
+ fields->end_col = (int)atol(rmp->startp[midx]);
return QF_OK;
}
@@ -1319,7 +1319,7 @@ static int qf_parse_fmt_t(regmatch_T *rmp, int midx, qffields_T *fields)
if (rmp->startp[midx] == NULL) {
return QF_FAIL;
}
- fields->type = (char)(*rmp->startp[midx]);
+ fields->type = *rmp->startp[midx];
return QF_OK;
}
@@ -1360,7 +1360,7 @@ static int qf_parse_fmt_r(regmatch_T *rmp, int midx, char **tail)
if (rmp->startp[midx] == NULL) {
return QF_FAIL;
}
- *tail = (char *)rmp->startp[midx];
+ *tail = rmp->startp[midx];
return QF_OK;
}
@@ -1372,7 +1372,7 @@ static int qf_parse_fmt_p(regmatch_T *rmp, int midx, qffields_T *fields)
return QF_FAIL;
}
fields->col = 0;
- for (char *match_ptr = (char *)rmp->startp[midx]; (char_u *)match_ptr != rmp->endp[midx];
+ for (char *match_ptr = rmp->startp[midx]; match_ptr != rmp->endp[midx];
match_ptr++) {
fields->col++;
if (*match_ptr == TAB) {
@@ -1392,7 +1392,7 @@ static int qf_parse_fmt_v(regmatch_T *rmp, int midx, qffields_T *fields)
if (rmp->startp[midx] == NULL) {
return QF_FAIL;
}
- fields->col = (int)atol((char *)rmp->startp[midx]);
+ fields->col = (int)atol(rmp->startp[midx]);
fields->use_viscol = true;
return QF_OK;
}
@@ -1409,7 +1409,7 @@ static int qf_parse_fmt_s(regmatch_T *rmp, int midx, qffields_T *fields)
len = CMDBUFFSIZE - 5;
}
STRCPY(fields->pattern, "^\\V");
- STRLCAT(fields->pattern, rmp->startp[midx], len + 4);
+ xstrlcat(fields->pattern, rmp->startp[midx], len + 4);
fields->pattern[len + 3] = '\\';
fields->pattern[len + 4] = '$';
fields->pattern[len + 5] = NUL;
@@ -1428,7 +1428,7 @@ static int qf_parse_fmt_o(regmatch_T *rmp, int midx, qffields_T *fields)
if (dsize > CMDBUFFSIZE) {
dsize = CMDBUFFSIZE;
}
- STRLCAT(fields->module, rmp->startp[midx], dsize);
+ xstrlcat(fields->module, rmp->startp[midx], dsize);
return QF_OK;
}
@@ -1564,7 +1564,7 @@ static int qf_parse_dir_pfx(int idx, qffields_T *fields, qf_list_T *qfl)
static int qf_parse_file_pfx(int idx, qffields_T *fields, qf_list_T *qfl, char *tail)
{
fields->valid = false;
- if (*fields->namebuf == NUL || os_path_exists((char_u *)fields->namebuf)) {
+ if (*fields->namebuf == NUL || os_path_exists(fields->namebuf)) {
if (*fields->namebuf && idx == 'P') {
qfl->qf_currfile = qf_push_dir(fields->namebuf, &qfl->qf_file_stack, true);
} else if (idx == 'Q') {
@@ -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;
@@ -2069,7 +2069,7 @@ static int qf_get_fnum(qf_list_T *qfl, char *directory, char *fname)
// This should normally be true, but if make works without
// "leaving directory"-messages we might have missed a
// directory change.
- if (!os_path_exists((char_u *)ptr)) {
+ if (!os_path_exists(ptr)) {
xfree(ptr);
directory = qf_guess_filepath(qfl, fname);
if (directory) {
@@ -2085,7 +2085,7 @@ static int qf_get_fnum(qf_list_T *qfl, char *directory, char *fname)
}
if (qf_last_bufname != NULL
- && STRCMP(bufname, qf_last_bufname) == 0
+ && strcmp(bufname, qf_last_bufname) == 0
&& bufref_valid(&qf_last_bufref)) {
buf = qf_last_bufref.br_buf;
xfree(ptr);
@@ -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;
}
@@ -2223,7 +2223,7 @@ static char *qf_guess_filepath(qf_list_T *qfl, char *filename)
xfree(fullname);
fullname = concat_fnames(ds_ptr->dirname, filename, true);
- if (os_path_exists((char_u *)fullname)) {
+ if (os_path_exists(fullname)) {
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);
@@ -3074,7 +3074,7 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel)
}
msg_puts(" ");
- char_u *tbuf = IObuff;
+ char *tbuf = IObuff;
size_t tbuflen = IOSIZE;
size_t len = STRLEN(qfp->qf_text) + 3;
@@ -3088,14 +3088,12 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel)
// with ^^^^.
qf_fmt_text((fname != NULL || qfp->qf_lnum != 0)
? skipwhite(qfp->qf_text) : qfp->qf_text,
- (char *)tbuf, (int)tbuflen);
+ tbuf, (int)tbuflen);
msg_prt_line(tbuf, false);
if (tbuf != IObuff) {
xfree(tbuf);
}
-
- ui_flush(); // show one line at a time
}
// ":clist": list all errors
@@ -3111,7 +3109,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 +3178,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) {
@@ -3238,7 +3236,7 @@ static void qf_msg(qf_info_T *qi, int which, char *lead)
memset(buf + len, ' ', 34 - len);
buf[34] = NUL;
}
- STRLCAT(buf, title, IOSIZE);
+ xstrlcat(buf, title, IOSIZE);
}
trunc_string(buf, buf, Columns - 1, IOSIZE);
msg(buf);
@@ -3263,13 +3261,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 +3391,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 +3465,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 +3556,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 +3708,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 +3745,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)
@@ -3898,7 +3896,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);
}
}
}
@@ -3967,7 +3965,7 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli
(char *)IObuff + len, IOSIZE - len);
}
- if (ml_append_buf(buf, lnum, IObuff,
+ if (ml_append_buf(buf, lnum, (char_u *)IObuff,
(colnr_T)STRLEN(IObuff) + 1, false) == FAIL) {
return FAIL;
}
@@ -4108,7 +4106,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 +4116,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,15 +4173,14 @@ 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
|| cmdidx == CMD_lgrep
|| cmdidx == CMD_grepadd
|| cmdidx == CMD_lgrepadd)
- && STRCMP("internal",
- *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0;
+ && strcmp("internal", *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0;
}
// Return the make/grep autocmd name.
@@ -4222,7 +4219,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 +4238,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)) {
@@ -4319,7 +4316,7 @@ static char *get_mef_name(void)
static int off = 0;
if (*p_mef == NUL) {
- name = (char *)vim_tempname();
+ name = vim_tempname();
if (name == NULL) {
emsg(_(e_notmp));
}
@@ -4328,7 +4325,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 +4829,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 +4895,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 +4907,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 +4978,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;
@@ -5075,7 +5072,7 @@ static void vgr_init_regmatch(regmmatch_T *regmatch, char *s)
static void vgr_display_fname(char *fname)
{
msg_start();
- char *p = (char *)msg_strtrunc((char_u *)fname, true);
+ char *p = msg_strtrunc(fname, true);
if (p == NULL) {
msg_outtrans(fname);
} else {
@@ -5140,6 +5137,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;
@@ -5154,7 +5152,7 @@ static bool vgr_match_buflines(qf_list_T *qfl, char *fname, buf_T *buf, char *sp
fname,
NULL,
duplicate_name ? 0 : buf->b_fnum,
- (char *)ml_get_buf(buf, regmatch->startpos[0].lnum + lnum, false),
+ ml_get_buf(buf, regmatch->startpos[0].lnum + lnum, false),
regmatch->startpos[0].lnum + lnum,
regmatch->endpos[0].lnum + lnum,
regmatch->startpos[0].col + 1,
@@ -5181,8 +5179,7 @@ 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);
+ char *const str = ml_get_buf(buf, lnum, false);
int score;
uint32_t matches[MAX_FUZZY_MATCHES];
const size_t sz = sizeof(matches) / sizeof(matches[0]);
@@ -5262,7 +5259,7 @@ static bool existing_swapfile(const buf_T *buf)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) {
- const char *const fname = (char *)buf->b_ml.ml_mfp->mf_fname;
+ const char *const fname = buf->b_ml.ml_mfp->mf_fname;
const size_t len = STRLEN(fname);
return fname[len - 1] != 'p' || fname[len - 2] != 'w';
@@ -5305,7 +5302,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) {
@@ -5419,7 +5416,7 @@ static int vgr_process_files(win_T *wp, qf_info_T *qi, vgr_args_T *cmd_args, boo
// directory we jumped to below.
if (buf == *first_match_buf
&& *target_dir == NULL
- && STRCMP(dirname_start, dirname_now) != 0) {
+ && strcmp(dirname_start, dirname_now) != 0) {
*target_dir = xstrdup(dirname_now);
}
@@ -5429,7 +5426,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);
}
@@ -5542,7 +5539,7 @@ static void restore_start_dir(char *dirname_start)
char *dirname_now = xmalloc(MAXPATHL);
os_dirname((char_u *)dirname_now, MAXPATHL);
- if (STRCMP(dirname_start, dirname_now) != 0) {
+ if (strcmp(dirname_start, dirname_now) != 0) {
// If the directory has changed, change it back by building up an
// appropriate ex command and executing it.
exarg_T ea = {
@@ -5609,7 +5606,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 +5674,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);
@@ -6500,7 +6497,7 @@ static int qf_setprop_curidx(qf_info_T *qi, qf_list_T *qfl, const dictitem_T *di
// If the specified index is '$', then use the last entry
if (di->di_tv.v_type == VAR_STRING
&& di->di_tv.vval.v_string != NULL
- && STRCMP(di->di_tv.vval.v_string, "$") == 0) {
+ && strcmp(di->di_tv.vval.v_string, "$") == 0) {
newidx = qfl->qf_count;
} else {
// Otherwise use the specified index
@@ -6951,7 +6948,7 @@ static void hgr_search_file(qf_list_T *qfl, char *fname, regmatch_T *p_regmatch)
}
linenr_T lnum = 1;
- while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) {
+ while (!vim_fgets((char_u *)IObuff, IOSIZE, fd) && !got_int) {
char *line = (char *)IObuff;
if (vim_regexec(p_regmatch, line, (colnr_T)0)) {
@@ -6970,8 +6967,8 @@ static void hgr_search_file(qf_list_T *qfl, char *fname, regmatch_T *p_regmatch)
line,
lnum,
0,
- (int)(p_regmatch->startp[0] - (char_u *)line) + 1, // col
- (int)(p_regmatch->endp[0] - (char_u *)line)
+ (int)(p_regmatch->startp[0] - line) + 1, // col
+ (int)(p_regmatch->endp[0] - line)
+ 1, // end_col
false, // vis_col
NULL, // search pattern
@@ -6980,13 +6977,13 @@ static void hgr_search_file(qf_list_T *qfl, char *fname, regmatch_T *p_regmatch)
true) // valid
== QF_FAIL) {
got_int = true;
- if ((char_u *)line != IObuff) {
+ if (line != IObuff) {
xfree(line);
}
break;
}
}
- if ((char_u *)line != IObuff) {
+ if (line != IObuff) {
xfree(line);
}
lnum++;
@@ -7033,7 +7030,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 +7059,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 +7090,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 +7166,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 +7260,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 +7271,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..9a8890a28a 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -137,7 +137,7 @@ static int re_multi_type(int c)
return NOT_MULTI;
}
-static char_u *reg_prev_sub = NULL;
+static char *reg_prev_sub = NULL;
/*
* REGEXP_INRANGE contains all characters which are always special in a []
@@ -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 {
@@ -1040,7 +1040,7 @@ static char_u *reg_getline(linenr_T lnum)
// Must have matched the "\n" in the last line.
return (char_u *)"";
}
- return ml_get_buf(rex.reg_buf, rex.reg_firstlnum + lnum, false);
+ return (char_u *)ml_get_buf(rex.reg_buf, rex.reg_firstlnum + lnum, false);
}
static char_u *reg_startzp[NSUBEXP]; // Workspace to mark beginning
@@ -1093,7 +1093,7 @@ void unref_extmatch(reg_extmatch_T *em)
static int reg_prev_class(void)
{
if (rex.input > rex.line) {
- return mb_get_class_tab(rex.input - 1 - utf_head_off(rex.line, rex.input - 1),
+ return mb_get_class_tab(rex.input - 1 - utf_head_off((char *)rex.line, (char *)rex.input - 1),
rex.reg_buf->b_chartab);
}
return -1;
@@ -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')) {
@@ -1282,7 +1282,7 @@ static int match_with_backref(linenr_T start_lnum, colnr_T start_col, linenr_T e
len = (int)STRLEN(p + ccol);
}
- if (cstrncmp(p + ccol, rex.input, &len) != 0) {
+ if (cstrncmp((char *)p + ccol, (char *)rex.input, &len) != 0) {
return RA_NOMATCH; // doesn't match
}
if (bytelen != NULL) {
@@ -1395,10 +1395,10 @@ static void mb_decompose(int c, int *c1, int *c2, int *c3)
}
}
-// Compare two strings, ignore case if rex.reg_ic set.
-// Return 0 if strings match, non-zero otherwise.
-// Correct the length "*n" when composing characters are ignored.
-static int cstrncmp(char_u *s1, char_u *s2, int *n)
+/// Compare two strings, ignore case if rex.reg_ic set.
+/// Return 0 if strings match, non-zero otherwise.
+/// Correct the length "*n" when composing characters are ignored.
+static int cstrncmp(char *s1, char *s2, int *n)
{
int result;
@@ -1406,12 +1406,12 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n)
result = STRNCMP(s1, s2, *n);
} else {
assert(*n >= 0);
- result = mb_strnicmp(s1, s2, (size_t)*n);
+ result = mb_strnicmp(s1, s2, (size_t)(*n));
}
// if it failed and it's utf8 and we want to combineignore:
if (result != 0 && rex.reg_icombine) {
- char_u *str1, *str2;
+ char *str1, *str2;
int c1, c2, c11, c12;
int junk;
@@ -1523,23 +1523,21 @@ static fptr_T do_Lower(int *d, int c)
return (fptr_T)do_Lower;
}
-/*
- * regtilde(): Replace tildes in the pattern by the old pattern.
- *
- * Short explanation of the tilde: It stands for the previous replacement
- * pattern. If that previous pattern also contains a ~ we should go back a
- * step further... But we insert the previous pattern into the current one
- * and remember that.
- * This still does not handle the case where "magic" changes. So require the
- * user to keep his hands off of "magic".
- *
- * The tildes are parsed once before the first call to vim_regsub().
- */
-char_u *regtilde(char_u *source, int magic, bool preview)
+/// regtilde(): Replace tildes in the pattern by the old pattern.
+///
+/// Short explanation of the tilde: It stands for the previous replacement
+/// pattern. If that previous pattern also contains a ~ we should go back a
+/// step further... But we insert the previous pattern into the current one
+/// and remember that.
+/// This still does not handle the case where "magic" changes. So require the
+/// user to keep his hands off of "magic".
+///
+/// The tildes are parsed once before the first call to vim_regsub().
+char *regtilde(char *source, int magic, bool preview)
{
- char_u *newsub = source;
- char_u *tmpsub;
- char_u *p;
+ char *newsub = source;
+ char *tmpsub;
+ char *p;
int len;
int prevlen;
@@ -1575,7 +1573,7 @@ char_u *regtilde(char_u *source, int magic, bool preview)
if (*p == '\\' && p[1]) { // skip escaped characters
p++;
}
- p += utfc_ptr2len((char *)p) - 1;
+ p += utfc_ptr2len(p) - 1;
}
}
@@ -1584,7 +1582,7 @@ char_u *regtilde(char_u *source, int magic, bool preview)
// Store a copy of newsub in reg_prev_sub. It is always allocated,
// because recursive calls may make the returned string invalid.
xfree(reg_prev_sub);
- reg_prev_sub = vim_strsave(newsub);
+ reg_prev_sub = xstrdup(newsub);
}
return newsub;
@@ -1623,14 +1621,14 @@ static int fill_submatch_list(int argc FUNC_ATTR_UNUSED, typval_T *argv, int arg
// There are always 10 list items in staticList10_T.
listitem_T *li = tv_list_first(listarg->vval.v_list);
for (int i = 0; i < 10; i++) {
- char_u *s = rsm.sm_match->startp[i];
+ char *s = rsm.sm_match->startp[i];
if (s == NULL || rsm.sm_match->endp[i] == NULL) {
s = NULL;
} else {
- s = vim_strnsave(s, (size_t)(rsm.sm_match->endp[i] - s));
+ s = xstrnsave(s, (size_t)(rsm.sm_match->endp[i] - s));
}
TV_LIST_ITEM_TV(li)->v_type = VAR_STRING;
- TV_LIST_ITEM_TV(li)->vval.v_string = (char *)s;
+ TV_LIST_ITEM_TV(li)->vval.v_string = s;
li = TV_LIST_ITEM_NEXT(argv->vval.v_list, li);
}
return argskip + 1;
@@ -1717,7 +1715,7 @@ int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *de
// When nesting more than a couple levels it's probably a mistake.
#define MAX_REGSUB_NESTING 4
-static char_u *eval_result[MAX_REGSUB_NESTING] = { NULL, NULL, NULL, NULL };
+static char *eval_result[MAX_REGSUB_NESTING] = { NULL, NULL, NULL, NULL };
#if defined(EXITFREE)
void free_resub_eval_result(void)
@@ -1826,21 +1824,21 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int des
eval_result[nested] = NULL;
} else {
char buf[NUMBUFLEN];
- eval_result[nested] = (char_u *)tv_get_string_buf_chk(&rettv, buf);
+ eval_result[nested] = (char *)tv_get_string_buf_chk(&rettv, buf);
if (eval_result[nested] != NULL) {
- eval_result[nested] = vim_strsave(eval_result[nested]);
+ eval_result[nested] = xstrdup(eval_result[nested]);
}
}
tv_clear(&rettv);
} else {
- eval_result[nested] = (char_u *)eval_to_string((char *)source + 2, NULL, true);
+ eval_result[nested] = eval_to_string((char *)source + 2, NULL, true);
}
nesting--;
if (eval_result[nested] != NULL) {
int had_backslash = false;
- for (s = eval_result[nested]; *s != NUL; MB_PTR_ADV(s)) {
+ for (s = (char_u *)eval_result[nested]; *s != NUL; MB_PTR_ADV(s)) {
// Change NL to CR, so that it becomes a line break,
// unless called from vim_regexec_nl().
// Skip over a backslashed character.
@@ -1862,9 +1860,9 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int des
}
if (had_backslash && (flags & REGSUB_BACKSLASH)) {
// Backslashes will be consumed, need to double them.
- s = vim_strsave_escaped(eval_result[nested], (char_u *)"\\");
+ s = vim_strsave_escaped((char_u *)eval_result[nested], (char_u *)"\\");
xfree(eval_result[nested]);
- eval_result[nested] = s;
+ eval_result[nested] = (char *)s;
}
dst += STRLEN(eval_result[nested]);
@@ -2008,11 +2006,11 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest, int des
}
}
} else {
- s = rex.reg_match->startp[no];
+ s = (char_u *)rex.reg_match->startp[no];
if (rex.reg_match->endp[no] == NULL) {
s = NULL;
} else {
- len = (int)(rex.reg_match->endp[no] - s);
+ len = (int)(rex.reg_match->endp[no] - (char *)s);
}
}
if (s != NULL) {
@@ -2112,36 +2110,33 @@ exit:
return (int)((dst - dest) + 1);
}
-/*
- * Call reg_getline() with the line numbers from the submatch. If a
- * substitute() was used the reg_maxline and other values have been
- * overwritten.
- */
-static char_u *reg_getline_submatch(linenr_T lnum)
+/// Call reg_getline() with the line numbers from the submatch. If a
+/// substitute() was used the reg_maxline and other values have been
+/// overwritten.
+static char *reg_getline_submatch(linenr_T lnum)
{
- char_u *s;
+ char *s;
linenr_T save_first = rex.reg_firstlnum;
linenr_T save_max = rex.reg_maxline;
rex.reg_firstlnum = rsm.sm_firstlnum;
rex.reg_maxline = rsm.sm_maxline;
- s = reg_getline(lnum);
+ s = (char *)reg_getline(lnum);
rex.reg_firstlnum = save_first;
rex.reg_maxline = save_max;
return s;
}
-/*
- * Used for the submatch() function: get the string from the n'th submatch in
- * allocated memory.
- * Returns NULL when not in a ":s" command and for a non-existing submatch.
- */
-char_u *reg_submatch(int no)
+/// Used for the submatch() function: get the string from the n'th submatch in
+/// allocated memory.
+///
+/// @return NULL when not in a ":s" command and for a non-existing submatch.
+char *reg_submatch(int no)
{
- char_u *retval = NULL;
- char_u *s;
+ char *retval = NULL;
+ char *s;
int round;
linenr_T lnum;
@@ -2215,7 +2210,7 @@ char_u *reg_submatch(int no)
if (s == NULL || rsm.sm_match->endp[no] == NULL) {
retval = NULL;
} else {
- retval = vim_strnsave(s, (size_t)(rsm.sm_match->endp[no] - s));
+ retval = xstrnsave(s, (size_t)(rsm.sm_match->endp[no] - s));
}
}
@@ -2250,16 +2245,16 @@ list_T *reg_submatch_list(int no)
list = tv_list_alloc(elnum - slnum + 1);
- s = (const char *)reg_getline_submatch(slnum) + scol;
+ s = reg_getline_submatch(slnum) + scol;
if (slnum == elnum) {
tv_list_append_string(list, s, ecol - scol);
} else {
tv_list_append_string(list, s, -1);
for (int i = 1; i < elnum - slnum; i++) {
- s = (const char *)reg_getline_submatch(slnum + i);
+ s = reg_getline_submatch(slnum + i);
tv_list_append_string(list, s, -1);
}
- s = (const char *)reg_getline_submatch(elnum);
+ s = reg_getline_submatch(elnum);
tv_list_append_string(list, s, ecol);
}
} else {
@@ -2469,12 +2464,12 @@ static bool vim_regexec_string(regmatch_T *rmp, char_u *line, colnr_T col, bool
&& result == NFA_TOO_EXPENSIVE) {
int save_p_re = (int)p_re;
int re_flags = (int)rmp->regprog->re_flags;
- char_u *pat = vim_strsave(((nfa_regprog_T *)rmp->regprog)->pattern);
+ char *pat = xstrdup(((nfa_regprog_T *)rmp->regprog)->pattern);
p_re = BACKTRACKING_ENGINE;
vim_regfree(rmp->regprog);
- report_re_switch(pat);
- rmp->regprog = vim_regcomp((char *)pat, re_flags);
+ report_re_switch((char_u *)pat);
+ rmp->regprog = vim_regcomp(pat, re_flags);
if (rmp->regprog != NULL) {
rmp->regprog->re_in_use = true;
result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl);
@@ -2560,16 +2555,16 @@ long vim_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum,
&& result == NFA_TOO_EXPENSIVE) {
int save_p_re = (int)p_re;
int re_flags = (int)rmp->regprog->re_flags;
- char_u *pat = vim_strsave(((nfa_regprog_T *)rmp->regprog)->pattern);
+ char *pat = xstrdup(((nfa_regprog_T *)rmp->regprog)->pattern);
p_re = BACKTRACKING_ENGINE;
regprog_T *prev_prog = rmp->regprog;
- report_re_switch(pat);
+ report_re_switch((char_u *)pat);
// checking for \z misuse was already done when compiling for NFA,
// allow all here
reg_do_extmatch = REX_ALL;
- rmp->regprog = vim_regcomp((char *)pat, re_flags);
+ rmp->regprog = vim_regcomp(pat, re_flags);
reg_do_extmatch = 0;
if (rmp->regprog == NULL) {
diff --git a/src/nvim/regexp_bt.c b/src/nvim/regexp_bt.c
index 769d2ceeef..59a6ed28af 100644
--- a/src/nvim/regexp_bt.c
+++ b/src/nvim/regexp_bt.c
@@ -1857,14 +1857,14 @@ static char_u *regatom(int *flagp)
char_u *lp;
ret = regnode(EXACTLY);
- lp = reg_prev_sub;
+ lp = (char_u *)reg_prev_sub;
while (*lp != NUL) {
regc(*lp++);
}
regc(NUL);
if (*reg_prev_sub != NUL) {
*flagp |= HASWIDTH;
- if ((lp - reg_prev_sub) == 1) {
+ if ((lp - (char_u *)reg_prev_sub) == 1) {
*flagp |= SIMPLE;
}
}
@@ -2469,7 +2469,7 @@ do_multibyte:
// Need to get composing character too.
for (;;) {
l = utf_ptr2len((char *)regparse);
- if (!utf_composinglike((char_u *)regparse, (char_u *)regparse + l)) {
+ if (!utf_composinglike(regparse, regparse + l)) {
break;
}
regmbc(utf_ptr2char((char *)regparse));
@@ -3192,7 +3192,7 @@ static int regrepeat(char_u *p, long maxcount)
case SKWORD:
case SKWORD + ADD_NL:
while (count < maxcount) {
- if (vim_iswordp_buf(scan, rex.reg_buf)
+ if (vim_iswordp_buf((char *)scan, rex.reg_buf)
&& (testval || !ascii_isdigit(*scan))) {
MB_PTR_ADV(scan);
} else if (*scan == NUL) {
@@ -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)) {
@@ -3828,7 +3829,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
break;
case KWORD:
- if (!vim_iswordp_buf(rex.input, rex.reg_buf)) {
+ if (!vim_iswordp_buf((char *)rex.input, rex.reg_buf)) {
status = RA_NOMATCH;
} else {
ADVANCE_REGINPUT();
@@ -3837,7 +3838,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
case SKWORD:
if (ascii_isdigit(*rex.input)
- || !vim_iswordp_buf(rex.input, rex.reg_buf)) {
+ || !vim_iswordp_buf((char *)rex.input, rex.reg_buf)) {
status = RA_NOMATCH;
} else {
ADVANCE_REGINPUT();
@@ -4038,14 +4039,14 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
} else {
// Need to match first byte again for multi-byte.
len = (int)STRLEN(opnd);
- if (cstrncmp(opnd, rex.input, &len) != 0) {
+ if (cstrncmp((char *)opnd, (char *)rex.input, &len) != 0) {
status = RA_NOMATCH;
}
}
// Check for following composing character, unless %C
// follows (skips over all composing chars).
if (status != RA_NOMATCH
- && utf_composinglike(rex.input, rex.input + len)
+ && utf_composinglike((char *)rex.input, (char *)rex.input + len)
&& !rex.reg_icombine
&& OP(next) != RE_COMPOSING) {
// raaron: This code makes a composing character get
@@ -4269,7 +4270,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
} else {
// Compare current input with back-ref in the same line.
len = (int)(rex.reg_endp[no] - rex.reg_startp[no]);
- if (cstrncmp(rex.reg_startp[no], rex.input, &len) != 0) {
+ if (cstrncmp((char *)rex.reg_startp[no], (char *)rex.input, &len) != 0) {
status = RA_NOMATCH;
}
}
@@ -4282,8 +4283,8 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
&& rex.reg_endpos[no].lnum == rex.lnum) {
// Compare back-ref within the current line.
len = rex.reg_endpos[no].col - rex.reg_startpos[no].col;
- if (cstrncmp(rex.line + rex.reg_startpos[no].col,
- rex.input, &len) != 0) {
+ if (cstrncmp((char *)rex.line + rex.reg_startpos[no].col,
+ (char *)rex.input, &len) != 0) {
status = RA_NOMATCH;
}
} else {
@@ -4319,7 +4320,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
if (re_extmatch_in != NULL
&& re_extmatch_in->matches[no] != NULL) {
int len = (int)STRLEN(re_extmatch_in->matches[no]);
- if (cstrncmp(re_extmatch_in->matches[no], rex.input, &len) != 0) {
+ if (cstrncmp((char *)re_extmatch_in->matches[no], (char *)rex.input, &len) != 0) {
status = RA_NOMATCH;
} else {
rex.input += len;
@@ -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]
@@ -4764,8 +4765,8 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
reg_getline(rp->rs_un.regsave.rs_u.pos.lnum);
rp->rs_un.regsave.rs_u.pos.col -=
- utf_head_off(line,
- line + rp->rs_un.regsave.rs_u.pos.col - 1)
+ utf_head_off((char *)line,
+ (char *)line + rp->rs_un.regsave.rs_u.pos.col - 1)
+ 1;
}
} else {
@@ -4974,13 +4975,13 @@ static long regtry(bt_regprog_T *prog, colnr_T col, proftime_T *tm, int *timed_o
&& reg_endzpos[i].lnum == reg_startzpos[i].lnum
&& reg_endzpos[i].col >= reg_startzpos[i].col) {
re_extmatch_out->matches[i] =
- vim_strnsave(reg_getline(reg_startzpos[i].lnum) + reg_startzpos[i].col,
- (size_t)(reg_endzpos[i].col - reg_startzpos[i].col));
+ (char_u *)xstrnsave((char *)reg_getline(reg_startzpos[i].lnum) + reg_startzpos[i].col,
+ (size_t)(reg_endzpos[i].col - reg_startzpos[i].col));
}
} else {
if (reg_startzp[i] != NULL && reg_endzp[i] != NULL) {
re_extmatch_out->matches[i] =
- vim_strnsave(reg_startzp[i], (size_t)(reg_endzp[i] - reg_startzp[i]));
+ (char_u *)xstrnsave((char *)reg_startzp[i], (size_t)(reg_endzp[i] - reg_startzp[i]));
}
}
}
@@ -5027,8 +5028,8 @@ static long bt_regexec_both(char_u *line, colnr_T col, proftime_T *tm, int *time
rex.reg_endpos = rex.reg_mmatch->endpos;
} else {
prog = (bt_regprog_T *)rex.reg_match->regprog;
- rex.reg_startp = rex.reg_match->startp;
- rex.reg_endp = rex.reg_match->endp;
+ rex.reg_startp = (char_u **)rex.reg_match->startp;
+ rex.reg_endp = (char_u **)rex.reg_match->endp;
}
// Be paranoid...
@@ -5068,14 +5069,14 @@ static long bt_regexec_both(char_u *line, colnr_T col, proftime_T *tm, int *time
// the loop to avoid overhead of conditions.
if (!rex.reg_ic) {
while ((s = (char_u *)vim_strchr((char *)s, c)) != NULL) {
- if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) {
+ if (cstrncmp((char *)s, (char *)prog->regmust, &prog->regmlen) == 0) {
break; // Found it.
}
MB_PTR_ADV(s);
}
} else {
while ((s = cstrchr(s, c)) != NULL) {
- if (cstrncmp(s, prog->regmust, &prog->regmlen) == 0) {
+ if (cstrncmp((char *)s, (char *)prog->regmust, &prog->regmlen) == 0) {
break; // Found it.
}
MB_PTR_ADV(s);
diff --git a/src/nvim/regexp_defs.h b/src/nvim/regexp_defs.h
index b313dfe877..b24ed350e8 100644
--- a/src/nvim/regexp_defs.h
+++ b/src/nvim/regexp_defs.h
@@ -127,7 +127,7 @@ typedef struct {
int has_zend; // pattern contains \ze
int has_backref; // pattern contains \1 .. \9
int reghasz;
- char_u *pattern;
+ char *pattern;
int nsubexp; // number of ()
int nstate;
nfa_state_T state[1]; // actually longer..
@@ -140,8 +140,8 @@ typedef struct {
*/
typedef struct {
regprog_T *regprog;
- char_u *startp[NSUBEXP];
- char_u *endp[NSUBEXP];
+ char *startp[NSUBEXP];
+ char *endp[NSUBEXP];
bool rm_ic;
} regmatch_T;
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 554def5b8a..fbd4e26c75 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -1959,9 +1959,9 @@ static int nfa_regatom(void)
emsg(_(e_nopresub));
return FAIL;
}
- for (lp = reg_prev_sub; *lp != NUL; MB_CPTR_ADV(lp)) {
+ for (lp = (char_u *)reg_prev_sub; *lp != NUL; MB_CPTR_ADV(lp)) {
EMIT(utf_ptr2char((char *)lp));
- if (lp != reg_prev_sub) {
+ if (lp != (char_u *)reg_prev_sub) {
EMIT(NFA_CONCAT);
}
}
@@ -5421,8 +5421,8 @@ retempty:
&& sub->list.multi[subidx].end_lnum == rex.lnum) {
len = sub->list.multi[subidx].end_col
- sub->list.multi[subidx].start_col;
- if (cstrncmp(rex.line + sub->list.multi[subidx].start_col,
- rex.input, &len) == 0) {
+ if (cstrncmp((char *)rex.line + sub->list.multi[subidx].start_col,
+ (char *)rex.input, &len) == 0) {
*bytelen = len;
return true;
}
@@ -5441,7 +5441,7 @@ retempty:
goto retempty;
}
len = (int)(sub->list.line[subidx].end - sub->list.line[subidx].start);
- if (cstrncmp(sub->list.line[subidx].start, rex.input, &len) == 0) {
+ if (cstrncmp((char *)sub->list.line[subidx].start, (char *)rex.input, &len) == 0) {
*bytelen = len;
return true;
}
@@ -5466,7 +5466,7 @@ static int match_zref(int subidx, int *bytelen)
}
len = (int)STRLEN(re_extmatch_in->matches[subidx]);
- if (cstrncmp(re_extmatch_in->matches[subidx], rex.input, &len) == 0) {
+ if (cstrncmp((char *)re_extmatch_in->matches[subidx], (char *)rex.input, &len) == 0) {
*bytelen = len;
return true;
}
@@ -5595,7 +5595,7 @@ static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T
}
if ((int)(rex.input - rex.line) >= state->val) {
rex.input -= state->val;
- rex.input -= utf_head_off(rex.line, rex.input);
+ rex.input -= utf_head_off((char *)rex.line, (char *)rex.input);
} else {
rex.input = rex.line;
}
@@ -6643,13 +6643,13 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
break;
case NFA_KWORD: // \k
- result = vim_iswordp_buf(rex.input, rex.reg_buf);
+ result = vim_iswordp_buf((char *)rex.input, rex.reg_buf);
ADD_STATE_IF_MATCH(t->state);
break;
case NFA_SKWORD: // \K
result = !ascii_isdigit(curc)
- && vim_iswordp_buf(rex.input, rex.reg_buf);
+ && vim_iswordp_buf((char *)rex.input, rex.reg_buf);
ADD_STATE_IF_MATCH(t->state);
break;
@@ -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);
}
@@ -7362,15 +7362,15 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm, int *ti
&& mpos->start_lnum == mpos->end_lnum
&& mpos->end_col >= mpos->start_col) {
re_extmatch_out->matches[i] =
- vim_strnsave(reg_getline(mpos->start_lnum) + mpos->start_col,
- (size_t)(mpos->end_col - mpos->start_col));
+ (char_u *)xstrnsave((char *)reg_getline(mpos->start_lnum) + mpos->start_col,
+ (size_t)(mpos->end_col - mpos->start_col));
}
} else {
struct linepos *lpos = &subs.synt.list.line[i];
if (lpos->start != NULL && lpos->end != NULL) {
re_extmatch_out->matches[i] =
- vim_strnsave(lpos->start, (size_t)(lpos->end - lpos->start));
+ (char_u *)xstrnsave((char *)lpos->start, (size_t)(lpos->end - lpos->start));
}
}
}
@@ -7402,8 +7402,8 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
rex.reg_endpos = rex.reg_mmatch->endpos;
} else {
prog = (nfa_regprog_T *)rex.reg_match->regprog;
- rex.reg_startp = rex.reg_match->startp;
- rex.reg_endp = rex.reg_match->endp;
+ rex.reg_startp = (char_u **)rex.reg_match->startp;
+ rex.reg_endp = (char_u **)rex.reg_match->endp;
}
// Be paranoid...
@@ -7593,7 +7593,7 @@ static regprog_T *nfa_regcomp(char_u *expr, int re_flags)
#endif
// Remember whether this pattern has any \z specials in it.
prog->reghasz = re_has_z;
- prog->pattern = vim_strsave(expr);
+ prog->pattern = xstrdup((char *)expr);
#ifdef REGEXP_DEBUG
nfa_regengine.expr = NULL;
#endif
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 914b21bb02..78a157f9fb 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
@@ -630,7 +651,7 @@ static bool path_is_after(char *buf, size_t buflen)
// "after" dir in SOME codepaths not not in ALL codepaths.
return buflen >= 5
&& (!(buflen >= 6) || vim_ispathsep(buf[buflen - 6]))
- && STRCMP(buf + buflen - 5, "after") == 0;
+ && strcmp(buf + buflen - 5, "after") == 0;
}
RuntimeSearchPath runtime_search_path_build(void)
@@ -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,14 +1058,14 @@ 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) {
continue;
}
STRLCPY(buf, fname, MAXPATHL);
- STRLCAT(buf, start_pat[i], sizeof buf);
+ xstrlcat(buf, start_pat[i], sizeof buf);
if (pack_has_entries(buf)) {
add_pack_dir_to_rtp(buf, true);
}
@@ -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++) {
@@ -1794,10 +1822,10 @@ static void cmd_source_buffer(const exarg_T *const eap)
if (ga.ga_len > 400) {
ga_set_growsize(&ga, MIN(ga.ga_len, 8000));
}
- ga_concat(&ga, (char *)ml_get(curr_lnum));
+ ga_concat(&ga, 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);
}
@@ -2093,14 +2121,14 @@ scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx)
// - If a script is deleted and another script is written, with a
// different name, the inode may be re-used.
si = &SCRIPT_ITEM(script_sctx.sc_sid);
- if (si->sn_name != NULL && FNAMECMP(si->sn_name, *fnamep) == 0) {
+ if (si->sn_name != NULL && path_fnamecmp(si->sn_name, *fnamep) == 0) {
// Found it!
break;
}
}
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 b471b93192..0e9bc9af49 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";
}
@@ -620,7 +620,7 @@ void setcursor_mayforce(bool force)
// With 'rightleft' set and the cursor on a double-wide character,
// position it on the leftmost column.
col = curwin->w_width_inner - curwin->w_wcol
- - ((utf_ptr2cells((char *)get_cursor_pos_ptr()) == 2
+ - ((utf_ptr2cells(get_cursor_pos_ptr()) == 2
&& vim_isprintc(gchar_cursor())) ? 2 : 1);
}
@@ -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);
}
@@ -911,8 +911,8 @@ static void recording_mode(int attr)
{
msg_puts_attr(_("recording"), attr);
if (!shortmess(SHM_RECORDING)) {
- char s[4];
- snprintf(s, ARRAY_SIZE(s), " @%c", reg_recording);
+ char s[7] = { ' ', '@', 0, 0, 0, 0, 0 };
+ utf_char2bytes(reg_recording, s + 2);
msg_puts_attr(s, 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[] = {
@@ -1335,7 +1328,9 @@ char *set_chars_option(win_T *wp, char_u **varp, bool set)
{ &wp->w_p_fcs_chars.diff, "diff", '-' },
{ &wp->w_p_fcs_chars.msgsep, "msgsep", ' ' },
{ &wp->w_p_fcs_chars.eob, "eob", '~' },
+ { &wp->w_p_fcs_chars.colorcol, "colorcol", ' ' },
};
+
struct chars_tab lcs_tab[] = {
{ &wp->w_p_lcs_chars.eol, "eol", NUL },
{ &wp->w_p_lcs_chars.ext, "extends", NUL },
@@ -1348,30 +1343,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 +1391,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 +1437,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 +1463,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 +1494,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 +1505,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..8477efed92 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -1,9 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * search.c: code for normal mode searching commands
- */
+// search.c: code for normal mode searching commands
#include <assert.h>
#include <inttypes.h>
@@ -106,10 +104,8 @@ static bool saved_spats_no_hlsearch = false;
static char_u *mr_pattern = NULL; // pattern used by search_regcomp()
static bool mr_pattern_alloced = false; // mr_pattern was allocated
-/*
- * Type used by find_pattern_in_path() to remember which included files have
- * been searched already.
- */
+// Type used by find_pattern_in_path() to remember which included files have
+// been searched already.
typedef struct SearchedFile {
FILE *fp; // File pointer
char_u *name; // Full name of file
@@ -139,9 +135,7 @@ int search_regcomp(char_u *pat, int pat_save, int pat_use, int options, regmmatc
rc_did_emsg = false;
magic = p_magic;
- /*
- * If no pattern given, use a previously defined pattern.
- */
+ // If no pattern given, use a previously defined pattern.
if (pat == NULL || *pat == NUL) {
if (pat_use == RE_LAST) {
i = last_idx;
@@ -161,7 +155,7 @@ int search_regcomp(char_u *pat, int pat_save, int pat_use, int options, regmmatc
magic = spats[i].magic;
no_smartcase = spats[i].no_scs;
} else if (options & SEARCH_HIS) { // put new pattern in history
- add_to_history(HIST_SEARCH, pat, true, NUL);
+ add_to_history(HIST_SEARCH, (char *)pat, true, NUL);
}
if (mr_pattern_alloced) {
@@ -170,24 +164,22 @@ 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;
}
- /*
- * Save the currently used pattern in the appropriate place,
- * unless the pattern should not be remembered.
- */
+ // Save the currently used pattern in the appropriate place,
+ // unless the pattern should not be remembered.
if (!(options & SEARCH_KEEP) && (cmdmod.cmod_flags & CMOD_KEEPPATTERNS) == 0) {
// search or global command
if (pat_save == RE_SEARCH || pat_save == RE_BOTH) {
- save_re_pat(RE_SEARCH, pat, magic);
+ save_re_pat(RE_SEARCH, (char *)pat, magic);
}
// substitute or global command
if (pat_save == RE_SUBST || pat_save == RE_BOTH) {
- save_re_pat(RE_SUBST, pat, magic);
+ save_re_pat(RE_SUBST, (char *)pat, magic);
}
}
@@ -200,19 +192,17 @@ int search_regcomp(char_u *pat, int pat_save, int pat_use, int options, regmmatc
return OK;
}
-/*
- * Get search pattern used by search_regcomp().
- */
+// Get search pattern used by search_regcomp().
char_u *get_search_pat(void)
{
return mr_pattern;
}
-void save_re_pat(int idx, char_u *pat, int magic)
+void save_re_pat(int idx, char *pat, int magic)
{
- if (spats[idx].pat != pat) {
+ if (spats[idx].pat != (char_u *)pat) {
free_spat(&spats[idx]);
- spats[idx].pat = vim_strsave(pat);
+ spats[idx].pat = (char_u *)xstrdup(pat);
spats[idx].magic = magic;
spats[idx].no_scs = no_smartcase;
spats[idx].timestamp = os_time();
@@ -220,16 +210,14 @@ 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);
}
}
-/*
- * Save the search patterns, so they can be restored later.
- * Used before/after executing autocommands and user functions.
- */
+// Save the search patterns, so they can be restored later.
+// Used before/after executing autocommands and user functions.
static int save_level = 0;
void save_search_patterns(void)
@@ -237,11 +225,11 @@ void save_search_patterns(void)
if (save_level++ == 0) {
saved_spats[0] = spats[0];
if (spats[0].pat != NULL) {
- saved_spats[0].pat = vim_strsave(spats[0].pat);
+ saved_spats[0].pat = (char_u *)xstrdup((char *)spats[0].pat);
}
saved_spats[1] = spats[1];
if (spats[1].pat != NULL) {
- saved_spats[1].pat = vim_strsave(spats[1].pat);
+ saved_spats[1].pat = (char_u *)xstrdup((char *)spats[1].pat);
}
saved_spats_last_idx = last_idx;
saved_spats_no_hlsearch = no_hlsearch;
@@ -308,7 +296,7 @@ void save_last_search_pattern(void)
saved_last_search_spat = spats[RE_SEARCH];
if (spats[RE_SEARCH].pat != NULL) {
- saved_last_search_spat.pat = vim_strsave(spats[RE_SEARCH].pat);
+ saved_last_search_spat.pat = (char_u *)xstrdup((char *)spats[RE_SEARCH].pat);
}
saved_last_idx = last_idx;
saved_no_hlsearch = no_hlsearch;
@@ -354,10 +342,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 +409,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)
@@ -452,19 +438,15 @@ char_u *last_search_pat(void)
return spats[last_idx].pat;
}
-/*
- * Reset search direction to forward. For "gd" and "gD" commands.
- */
+// Reset search direction to forward. For "gd" and "gD" commands.
void reset_search_dir(void)
{
spats[0].off.dir = '/';
set_vv_searchforward();
}
-/*
- * Set the last search pattern. For ":let @/ =" and ShaDa file.
- * Also set the saved search pattern, so that this works in an autocommand.
- */
+// Set the last search pattern. For ":let @/ =" and ShaDa file.
+// Also set the saved search pattern, so that this works in an autocommand.
void set_last_search_pat(const char_u *s, int idx, int magic, int setlast)
{
free_spat(&spats[idx]);
@@ -480,8 +462,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;
@@ -492,28 +474,26 @@ void set_last_search_pat(const char_u *s, int idx, int magic, int setlast)
if (spats[idx].pat == NULL) {
saved_spats[idx].pat = NULL;
} else {
- saved_spats[idx].pat = vim_strsave(spats[idx].pat);
+ saved_spats[idx].pat = (char_u *)xstrdup((char *)spats[idx].pat);
}
saved_spats_last_idx = last_idx;
}
// 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);
}
}
-/*
- * Get a regexp program for the last used search pattern.
- * This is used for highlighting all matches in a window.
- * Values returned in regmatch->regprog and regmatch->rmm_ic.
- */
+// Get a regexp program for the last used search pattern.
+// This is used for highlighting all matches in a window.
+// Values returned in regmatch->regprog and regmatch->rmm_ic.
void last_pat_prog(regmmatch_T *regmatch)
{
if (spats[last_idx].pat == NULL) {
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--;
}
@@ -580,9 +560,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
return FAIL;
}
- /*
- * find the string
- */
+ // find the string
do { // loop for count
// When not accepting a match at the start position set "extra_col" to a
// non-zero value. Don't do that when starting at MAXCOL, since MAXCOL + 1
@@ -593,7 +571,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
&& pos->lnum <= buf->b_ml.ml_line_count
&& pos->col < MAXCOL - 2) {
// Watch out for the "col" being MAXCOL - 2, used in a closed fold.
- ptr = ml_get_buf(buf, pos->lnum, false);
+ ptr = (char_u *)ml_get_buf(buf, pos->lnum, false);
if ((int)STRLEN(ptr) <= pos->col) {
start_char_len = 1;
} else {
@@ -610,31 +588,29 @@ 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
}
- /*
- * Start searching in current line, unless searching backwards and
- * we're in column 0.
- * If we are searching backwards, in column 0, and not including the
- * current position, gain some efficiency by skipping back a line.
- * Otherwise begin the search in the current line.
- */
+ // Start searching in current line, unless searching backwards and
+ // we're in column 0.
+ // If we are searching backwards, in column 0, and not including the
+ // current position, gain some efficiency by skipping back a line.
+ // Otherwise begin the search in the current line.
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)) {
@@ -666,14 +642,12 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
if (lnum + matchpos.lnum > buf->b_ml.ml_line_count) {
ptr = (char_u *)"";
} else {
- ptr = ml_get_buf(buf, lnum + matchpos.lnum, false);
+ ptr = (char_u *)ml_get_buf(buf, lnum + matchpos.lnum, false);
}
- /*
- * Forward search in the first line: match should be after
- * the start position. If not, continue at the end of the
- * match (this is vi compatible) or on the next char.
- */
+ // Forward search in the first line: match should be after
+ // the start position. If not, continue at the end of the
+ // match (this is vi compatible) or on the next char.
if (dir == FORWARD && at_first_line) {
match_ok = true;
// When the match starts in a next line it's certainly
@@ -689,11 +663,9 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
: ((int)matchpos.col
- (ptr[matchpos.col] == NUL)
< (int)start_pos.col + extra_col))) {
- /*
- * If vi-compatible searching, continue at the end
- * of the match, otherwise continue one position
- * forward.
- */
+ // If vi-compatible searching, continue at the end
+ // of the match, otherwise continue one position
+ // forward.
if (vim_strchr(p_cpo, CPO_SEARCH) != NULL) {
if (nmatched > 1) {
// end is in next line, thus no match in
@@ -739,20 +711,18 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
}
// Need to get the line pointer again, a multi-line search may
// have made it invalid.
- ptr = ml_get_buf(buf, lnum, false);
+ ptr = (char_u *)ml_get_buf(buf, lnum, false);
}
if (!match_ok) {
continue;
}
}
if (dir == BACKWARD) {
- /*
- * Now, if there are multiple matches on this line,
- * we have to get the last one. Or the last one before
- * the cursor, if we're on that line.
- * When putting the new cursor at the end, compare
- * relative to the end of the match.
- */
+ // Now, if there are multiple matches on this line,
+ // we have to get the last one. Or the last one before
+ // the cursor, if we're on that line.
+ // When putting the new cursor at the end, compare
+ // relative to the end of the match.
match_ok = false;
for (;;) {
// Remember a position that is before the start
@@ -824,13 +794,11 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
}
// Need to get the line pointer again, a
// multi-line search may have made it invalid.
- ptr = ml_get_buf(buf, lnum + matchpos.lnum, false);
+ ptr = (char_u *)ml_get_buf(buf, lnum + matchpos.lnum, false);
}
- /*
- * If there is only a match after the cursor, skip
- * this match.
- */
+ // If there is only a match after the cursor, skip
+ // this match.
if (!match_ok) {
continue;
}
@@ -854,8 +822,8 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
} else {
pos->col--;
if (pos->lnum <= buf->b_ml.ml_line_count) {
- ptr = ml_get_buf(buf, pos->lnum, false);
- pos->col -= utf_head_off(ptr, ptr + pos->col);
+ ptr = (char_u *)ml_get_buf(buf, pos->lnum, false);
+ pos->col -= utf_head_off((char *)ptr, (char *)ptr + pos->col);
}
}
if (end_pos != NULL) {
@@ -901,7 +869,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 +959,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 +974,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
@@ -1044,25 +1012,19 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
size_t len;
bool has_offset = false;
- /*
- * A line offset is not remembered, this is vi compatible.
- */
+ // A line offset is not remembered, this is vi compatible.
if (spats[0].off.line && vim_strchr(p_cpo, CPO_LINEOFF) != NULL) {
spats[0].off.line = false;
spats[0].off.off = 0;
}
- /*
- * Save the values for when (options & SEARCH_KEEP) is used.
- * (there is no "if ()" around this because gcc wants them initialized)
- */
+ // Save the values for when (options & SEARCH_KEEP) is used.
+ // (there is no "if ()" around this because gcc wants them initialized)
old_off = spats[0].off;
pos = curwin->w_cursor; // start searching at the cursor position
- /*
- * Find out the direction of the search.
- */
+ // Find out the direction of the search.
if (dirc == 0) {
dirc = (char_u)spats[0].off.dir;
} else {
@@ -1089,17 +1051,13 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
}
}
- /*
- * Turn 'hlsearch' highlighting back on.
- */
+ // 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);
}
- /*
- * Repeat the search when pattern followed by ';', e.g. "/foo/;?bar".
- */
+ // Repeat the search when pattern followed by ';', e.g. "/foo/;?bar".
for (;;) {
bool show_top_bot_msg = false;
@@ -1121,12 +1079,10 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
}
if (pat != NULL && *pat != NUL) { // look for (new) offset
- /*
- * Find end of regular expression.
- * If there is a matching '/' or '?', toss it.
- */
+ // Find end of regular expression.
+ // 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 +1093,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
@@ -1252,7 +1208,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
memmove(msgbuf + STRLEN(p) + 1, off_buf, off_len);
}
- trunc = msg_strtrunc(msgbuf, true);
+ trunc = (char_u *)msg_strtrunc((char *)msgbuf, true);
if (trunc != NULL) {
xfree(msgbuf);
msgbuf = trunc;
@@ -1263,7 +1219,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
@@ -1289,16 +1245,14 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
}
}
- /*
- * If there is a character offset, subtract it from the current
- * position, so we don't get stuck at "?pat?e+2" or "/pat/s-2".
- * Skip this if pos.col is near MAXCOL (closed fold).
- * This is not done for a line offset, because then we would not be vi
- * compatible.
- */
+ // If there is a character offset, subtract it from the current
+ // position, so we don't get stuck at "?pat?e+2" or "/pat/s-2".
+ // Skip this if pos.col is near MAXCOL (closed fold).
+ // This is not done for a line offset, because then we would not be vi
+ // compatible.
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 +1262,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;
}
@@ -1352,9 +1306,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
apply_autocmds(EVENT_SEARCHWRAPPED, NULL, NULL, false, NULL);
}
- /*
- * Add character and/or line offset
- */
+ // Add character and/or line offset
if (!(options & SEARCH_NOOF) || (pat != NULL && *pat == ';')) {
pos_T org_pos = pos;
@@ -1435,7 +1387,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)) {
@@ -1446,15 +1398,13 @@ end_do_search:
return retval;
}
-/*
- * search_for_exact_line(buf, pos, dir, pat)
- *
- * Search for a line starting with the given pattern (ignoring leading
- * white-space), starting from pos and going in direction "dir". "pos" will
- * contain the position of the match found. Blank lines match only if
- * ADDING is set. If p_ic is set then the pattern must be in lowercase.
- * Return OK for success, or FAIL if no line found.
- */
+// search_for_exact_line(buf, pos, dir, pat)
+//
+// Search for a line starting with the given pattern (ignoring leading
+// white-space), starting from pos and going in direction "dir". "pos" will
+// contain the position of the match found. Blank lines match only if
+// ADDING is set. If p_ic is set then the pattern must be in lowercase.
+// Return OK for success, or FAIL if no line found.
int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
{
linenr_T start = 0;
@@ -1493,22 +1443,21 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
if (start == 0) {
start = pos->lnum;
}
- ptr = ml_get_buf(buf, pos->lnum, false);
+ ptr = (char_u *)ml_get_buf(buf, pos->lnum, false);
p = (char_u *)skipwhite((char *)ptr);
pos->col = (colnr_T)(p - ptr);
// 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((char *)p, (char *)pat, (size_t)ins_compl_len())
+ : STRNCMP(p, pat, ins_compl_len())) == 0) {
return OK;
}
}
@@ -1516,16 +1465,12 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
return FAIL;
}
-/*
- * Character Searches
- */
+// 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
{
@@ -1579,7 +1524,7 @@ int searchc(cmdarg_T *cap, int t_cmd)
cap->oap->inclusive = true;
}
- p = get_cursor_line_ptr();
+ p = (char_u *)get_cursor_line_ptr();
col = curwin->w_cursor.col;
len = (int)STRLEN(p);
@@ -1594,7 +1539,7 @@ int searchc(cmdarg_T *cap, int t_cmd)
if (col == 0) {
return FAIL;
}
- col -= utf_head_off(p, p + col - 1) + 1;
+ col -= utf_head_off((char *)p, (char *)p + col - 1) + 1;
}
if (lastc_bytelen == 1) {
if (p[col] == c && stop) {
@@ -1615,7 +1560,7 @@ int searchc(cmdarg_T *cap, int t_cmd)
col += lastc_bytelen - 1;
} else {
// To previous char, which may be multi-byte.
- col -= utf_head_off(p, p + col);
+ col -= utf_head_off((char *)p, (char *)p + col);
}
}
curwin->w_cursor.col = col;
@@ -1623,15 +1568,11 @@ int searchc(cmdarg_T *cap, int t_cmd)
return OK;
}
-/*
- * "Other" Searches
- */
+// "Other" Searches
-/*
- * findmatch - find the matching paren or brace
- *
- * Improvement over vi: Braces inside quotes are ignored.
- */
+// findmatch - find the matching paren or brace
+//
+// Improvement over vi: Braces inside quotes are ignored.
pos_T *findmatch(oparg_T *oap, int initc)
{
return findmatchlimit(oap, initc, 0, 0);
@@ -1646,7 +1587,7 @@ static bool check_prevcol(char_u *linep, int col, int ch, int *prevcol)
{
col--;
if (col > 0) {
- col -= utf_head_off(linep, linep + col);
+ col -= utf_head_off((char *)linep, (char *)linep + col);
}
if (prevcol) {
*prevcol = col;
@@ -1654,22 +1595,21 @@ static bool check_prevcol(char_u *linep, int col, int ch, int *prevcol)
return col >= 0 && linep[col] == ch;
}
-/*
- * Raw string start is found at linep[startpos.col - 1].
- * Return true if the matching end can be found between startpos and endpos.
- */
-static bool find_rawstring_end(char_u *linep, pos_T *startpos, pos_T *endpos)
+/// Raw string start is found at linep[startpos.col - 1].
+///
+/// @return true if the matching end can be found between startpos and endpos.
+static bool find_rawstring_end(char *linep, pos_T *startpos, pos_T *endpos)
{
- char_u *p;
+ char *p;
linenr_T lnum;
for (p = linep + startpos->col + 1; *p && *p != '('; p++) {}
size_t delim_len = (size_t)((p - linep) - startpos->col - 1);
- char_u *delim_copy = vim_strnsave(linep + startpos->col + 1, delim_len);
+ char *delim_copy = xstrnsave(linep + startpos->col + 1, delim_len);
bool found = false;
for (lnum = startpos->lnum; lnum <= endpos->lnum; lnum++) {
- char_u *line = ml_get(lnum);
+ char *line = ml_get(lnum);
for (p = line + (lnum == startpos->lnum ? startpos->col + 1 : 0); *p; p++) {
if (lnum == endpos->lnum && (colnr_T)(p - line) >= endpos->col) {
@@ -1697,61 +1637,58 @@ 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++;
}
}
}
-/*
- * findmatchlimit -- find the matching paren or brace, if it exists within
- * maxtravel lines of the cursor. A maxtravel of 0 means search until falling
- * off the edge of the file.
- *
- * "initc" is the character to find a match for. NUL means to find the
- * character at or after the cursor. Special values:
- * '*' look for C-style comment / *
- * '/' look for C-style comment / *, ignoring comment-end
- * '#' look for preprocessor directives
- * 'R' look for raw string start: R"delim(text)delim" (only backwards)
- *
- * flags: FM_BACKWARD search backwards (when initc is '/', '*' or '#')
- * FM_FORWARD search forwards (when initc is '/', '*' or '#')
- * FM_BLOCKSTOP stop at start/end of block ({ or } in column 0)
- * FM_SKIPCOMM skip comments (not implemented yet!)
- *
- * "oap" is only used to set oap->motion_type for a linewise motion, it can be
- * NULL
- */
-
+// findmatchlimit -- find the matching paren or brace, if it exists within
+// maxtravel lines of the cursor. A maxtravel of 0 means search until falling
+// off the edge of the file.
+//
+// "initc" is the character to find a match for. NUL means to find the
+// character at or after the cursor. Special values:
+// '*' look for C-style comment / *
+// '/' look for C-style comment / *, ignoring comment-end
+// '#' look for preprocessor directives
+// 'R' look for raw string start: R"delim(text)delim" (only backwards)
+//
+// flags: FM_BACKWARD search backwards (when initc is '/', '*' or '#')
+// FM_FORWARD search forwards (when initc is '/', '*' or '#')
+// FM_BLOCKSTOP stop at start/end of block ({ or } in column 0)
+// FM_SKIPCOMM skip comments (not implemented yet!)
+//
+// "oap" is only used to set oap->motion_type for a linewise motion, it can be
+// NULL
pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
{
static pos_T pos; // current search position
@@ -1773,7 +1710,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
pos = curwin->w_cursor;
pos.coladd = 0;
- char_u *linep = ml_get(pos.lnum); // pointer to current line
+ char_u *linep = (char_u *)ml_get(pos.lnum); // pointer to current line
// vi compatible matching
bool cpo_match = (vim_strchr(p_cpo, CPO_MATCH) != NULL);
@@ -1789,12 +1726,10 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
dir = 0;
}
- /*
- * if initc given, look in the table for the matching character
- * '/' and '*' are special cases: look for start or end of comment.
- * When '/' is used, we ignore running backwards into a star-slash, for
- * "[*" command, we just want to find any comment.
- */
+ // if initc given, look in the table for the matching character
+ // '/' and '*' are special cases: look for start or end of comment.
+ // When '/' is used, we ignore running backwards into a star-slash, for
+ // "[*" command, we just want to find any comment.
if (initc == '/' || initc == '*' || initc == 'R') {
comment_dir = dir;
if (initc == '/') {
@@ -1812,18 +1747,14 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
return NULL;
}
} else {
- /*
- * Either initc is '#', or no initc was given and we need to look
- * under the cursor.
- */
+ // Either initc is '#', or no initc was given and we need to look
+ // under the cursor.
if (initc == '#') {
hash_dir = dir;
} else {
- /*
- * initc was not given, must look for something to match under
- * or near the cursor.
- * Only check for special things when 'cpo' doesn't have '%'.
- */
+ // initc was not given, must look for something to match under
+ // or near the cursor.
+ // Only check for special things when 'cpo' doesn't have '%'.
if (!cpo_match) {
// Are we before or at #if, #else etc.?
ptr = (char_u *)skipwhite((char *)linep);
@@ -1857,18 +1788,14 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
}
}
- /*
- * If we are not on a comment or the # at the start of a line, then
- * look for brace anywhere on this line after the cursor.
- */
+ // If we are not on a comment or the # at the start of a line, then
+ // look for brace anywhere on this line after the cursor.
if (!hash_dir && !comment_dir) {
- /*
- * Find the brace under or after the cursor.
- * If beyond the end of the line, use the last character in
- * the line.
- */
+ // Find the brace under or after the cursor.
+ // If beyond the end of the line, use the last character in
+ // the line.
if (linep[pos.col] == NUL && pos.col) {
- --pos.col;
+ pos.col--;
}
for (;;) {
initc = utf_ptr2char((char *)linep + pos.col);
@@ -1902,9 +1829,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
}
}
if (hash_dir) {
- /*
- * Look for matching #if, #else, #elif, or #endif
- */
+ // Look for matching #if, #else, #elif, or #endif
if (oap != NULL) {
oap->motion_type = kMTLineWise; // Linewise for this case only
}
@@ -1928,7 +1853,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
break;
}
pos.lnum += hash_dir;
- linep = ml_get(pos.lnum);
+ linep = (char_u *)ml_get(pos.lnum);
line_breakcheck(); // check for CTRL-C typed
ptr = (char_u *)skipwhite((char *)linep);
if (*ptr != '#') {
@@ -1982,17 +1907,15 @@ 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
}
while (!got_int) {
- /*
- * Go to the next position, forward or backward. We could use
- * inc() and dec() here, but that is much slower
- */
+ // Go to the next position, forward or backward. We could use
+ // inc() and dec() here, but that is much slower
if (backwards) {
// char to match is inside of comment, don't search outside
if (lispcomm && pos.col < (colnr_T)comment_col) {
@@ -2002,20 +1925,20 @@ 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;
}
- linep = ml_get(pos.lnum);
+ linep = (char_u *)ml_get(pos.lnum);
pos.col = (colnr_T)STRLEN(linep); // pos.col on trailing NUL
do_quotes = -1;
line_breakcheck();
// 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) {
@@ -2023,7 +1946,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
}
} else {
pos.col--;
- pos.col -= utf_head_off(linep, linep + pos.col);
+ pos.col -= utf_head_off((char *)linep, (char *)linep + pos.col);
}
} else { // forward search
if (linep[pos.col] == NUL
@@ -2037,18 +1960,18 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
|| lispcomm) {
break;
}
- ++pos.lnum;
+ pos.lnum++;
if (maxtravel && traveled++ > maxtravel) {
break;
}
- linep = ml_get(pos.lnum);
+ linep = (char_u *)ml_get(pos.lnum);
pos.col = 0;
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);
@@ -2073,10 +1996,8 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
return &pos;
}
} else { // Searching backwards
- /*
- * A comment may contain / * or / /, it may also start or end
- * with / * /. Ignore a / * after / / and after *.
- */
+ // A comment may contain / * or / /, it may also start or end
+ // with / * /. Ignore a / * after / / and after *.
if (pos.col == 0) {
continue;
} else if (raw_string) {
@@ -2087,13 +2008,13 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
// delimiter we can check if it ends before where we
// started searching, or before the previously found
// raw string start.
- if (!find_rawstring_end(linep, &pos,
+ if (!find_rawstring_end((char *)linep, &pos,
count > 0 ? &match_pos : &curwin->w_cursor)) {
count++;
match_pos = pos;
match_pos.col--;
}
- linep = ml_get(pos.lnum); // may have been released
+ linep = (char_u *)ml_get(pos.lnum); // may have been released
}
} else if (linep[pos.col - 1] == '/'
&& linep[pos.col] == '*'
@@ -2119,20 +2040,16 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
continue;
}
- /*
- * If smart matching ('cpoptions' does not contain '%'), braces inside
- * of quotes are ignored, but only if there is an even number of
- * quotes in the line.
- */
+ // If smart matching ('cpoptions' does not contain '%'), braces inside
+ // of quotes are ignored, but only if there is an even number of
+ // quotes in the line.
if (cpo_match) {
do_quotes = 0;
} else if (do_quotes == -1) {
- /*
- * Count the number of quotes in the line, skipping \" and '"'.
- * Watch out for "\\".
- */
+ // Count the number of quotes in the line, skipping \" and '"'.
+ // 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);
}
@@ -2146,10 +2063,8 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
}
do_quotes &= 1; // result is 1 with even number of quotes
- /*
- * If we find an uneven count, check current line and previous
- * one for a '\' at the end.
- */
+ // If we find an uneven count, check current line and previous
+ // one for a '\' at the end.
if (!do_quotes) {
inquote = false;
if (ptr[-1] == '\\') {
@@ -2163,7 +2078,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
}
}
if (pos.lnum > 1) {
- ptr = ml_get(pos.lnum - 1);
+ ptr = (char_u *)ml_get(pos.lnum - 1);
if (*ptr && *(ptr + STRLEN(ptr) - 1) == '\\') {
do_quotes = 1;
if (start_in_quotes == kNone) {
@@ -2177,7 +2092,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
}
// ml_get() only keeps one line, need to get linep again
- linep = ml_get(pos.lnum);
+ linep = (char_u *)ml_get(pos.lnum);
}
}
}
@@ -2185,17 +2100,15 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
start_in_quotes = kFalse;
}
- /*
- * If 'smartmatch' is set:
- * Things inside quotes are ignored by setting 'inquote'. If we
- * find a quote without a preceding '\' invert 'inquote'. At the
- * end of a line not ending in '\' we reset 'inquote'.
- *
- * In lines with an uneven number of quotes (without preceding '\')
- * we do not know which part to ignore. Therefore we only set
- * inquote if the number of quotes in a line is even, unless this
- * line or the previous one ends in a '\'. Complicated, isn't it?
- */
+ // If 'smartmatch' is set:
+ // Things inside quotes are ignored by setting 'inquote'. If we
+ // find a quote without a preceding '\' invert 'inquote'. At the
+ // end of a line not ending in '\' we reset 'inquote'.
+ //
+ // In lines with an uneven number of quotes (without preceding '\')
+ // we do not know which part to ignore. Therefore we only set
+ // inquote if the number of quotes in a line is even, unless this
+ // line or the previous one ends in a '\'. Complicated, isn't it?
const int c = utf_ptr2char((char *)linep + pos.col);
switch (c) {
case NUL:
@@ -2212,7 +2125,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;
}
@@ -2224,13 +2137,11 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
}
break;
- /*
- * If smart matching ('cpoptions' does not contain '%'):
- * Skip things in single quotes: 'x' or '\x'. Be careful for single
- * single quotes, eg jon's. Things like '\233' or '\x3f' are not
- * skipped, there is never a brace in them.
- * Ignore this when finding matches for `'.
- */
+ // If smart matching ('cpoptions' does not contain '%'):
+ // Skip things in single quotes: 'x' or '\x'. Be careful for single
+ // single quotes, eg jon's. Things like '\233' or '\x3f' are not
+ // skipped, there is never a brace in them.
+ // Ignore this when finding matches for `'.
case '\'':
if (!cpo_match && initc != '\'' && findc != '\'') {
if (backwards) {
@@ -2258,10 +2169,8 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
FALLTHROUGH;
default:
- /*
- * For Lisp skip over backslashed (), {} and [].
- * (actually, we skip #\( et al)
- */
+ // For Lisp skip over backslashed (), {} and [].
+ // (actually, we skip #\( et al)
if (curbuf->b_p_lisp
&& vim_strchr("(){}[]", c) != NULL
&& pos.col > 1
@@ -2306,15 +2215,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 +2236,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 +2245,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++;
@@ -2373,11 +2282,9 @@ void showmatch(int c)
colnr_T save_dollar_vcol;
char_u *p;
- /*
- * Only show match for chars in the 'matchpairs' option.
- */
+ // 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 +2321,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;
@@ -2431,10 +2338,8 @@ void showmatch(int c)
// and has a higher column number.
dollar_vcol = save_dollar_vcol;
- /*
- * brief pause, unless 'm' is present in 'cpo' and a character is
- * available.
- */
+ // brief pause, unless 'm' is present in 'cpo' and a character is
+ // available.
if (vim_strchr(p_cpo, CPO_SHOWMATCH) != NULL) {
os_delay((uint64_t)p_mat * 100L + 8, true);
} else if (!char_avail()) {
@@ -2449,1814 +2354,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 +2486,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 +2496,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,14 +2553,12 @@ 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;
- p = (char_u *)skipwhite((char *)ml_get(lnum));
+ p = (char_u *)skipwhite(ml_get(lnum));
return *p == NUL;
}
@@ -4622,7 +2717,7 @@ static void update_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, searchst
}
if (done_search) {
xfree(lastpat);
- lastpat = vim_strsave(spats[last_idx].pat);
+ lastpat = (char_u *)xstrdup((char *)spats[last_idx].pat);
chgtick = (int)buf_get_changedtick(curbuf);
lbuf = curbuf;
lastpos = p;
@@ -4637,7 +2732,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;
@@ -4732,7 +2827,7 @@ void f_searchcount(typval_T *argvars, typval_T *rettv, FunPtr fptr)
goto the_end;
}
xfree(spats[last_idx].pat);
- spats[last_idx].pat = vim_strsave(pattern);
+ spats[last_idx].pat = (char_u *)xstrdup((char *)pattern);
}
if (spats[last_idx].pat == NULL || *spats[last_idx].pat == NUL) {
goto the_end; // the previous pattern was never defined
@@ -4869,7 +2964,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);
@@ -5008,7 +3103,7 @@ bool fuzzy_match(char_u *const str, const char_u *const pat_arg, const bool matc
*outScore = 0;
- char_u *const save_pat = vim_strsave(pat_arg);
+ char_u *const save_pat = (char_u *)xstrdup((char *)pat_arg);
char_u *pat = save_pat;
char_u *p = pat;
@@ -5287,13 +3382,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);
}
@@ -5303,13 +3398,13 @@ void f_matchfuzzypos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// mark.
static char_u *get_line_and_copy(linenr_T lnum, char_u *buf)
{
- char_u *line = ml_get(lnum);
+ char_u *line = (char_u *)ml_get(lnum);
STRLCPY(buf, line, LSIZE);
return 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 +3446,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 +3456,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 +3470,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,19 +3506,19 @@ 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]
- - incl_regmatch.startp[0]),
- FNAME_EXP|FNAME_INCL|FNAME_REL,
- 1L, p_fname);
+ new_fname = (char_u *)find_file_name_in_path(incl_regmatch.startp[0],
+ (size_t)(incl_regmatch.endp[0]
+ - incl_regmatch.startp[0]),
+ FNAME_EXP|FNAME_INCL|FNAME_REL,
+ 1L, (char *)p_fname);
} else {
// Use text after match with 'include'.
- new_fname = file_name_in_line(incl_regmatch.endp[0], 0,
+ new_fname = file_name_in_line((char_u *)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++) {
@@ -5441,7 +3535,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
msg_putchar('\n'); // cursor below last one */
if (!got_int) { // don't display if 'q' typed at "--more--"
// message
- msg_home_replace_hl(new_fname);
+ msg_home_replace_hl((char *)new_fname);
msg_puts(_(" (includes previously listed match)"));
prev_fname = NULL;
}
@@ -5471,7 +3565,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
for (i = 0; i < depth_displayed; i++) {
msg_puts(" ");
}
- msg_home_replace(files[depth_displayed].name);
+ msg_home_replace((char *)files[depth_displayed].name);
msg_puts(" -->\n");
}
if (!got_int) { // don't display if 'q' typed
@@ -5482,28 +3576,26 @@ 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.
- */
+ // 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];
+ p = (char_u *)incl_regmatch.startp[0];
i = (int)(incl_regmatch.endp[0]
- incl_regmatch.startp[0]);
} else {
// find the file name after the end of the match
- for (p = incl_regmatch.endp[0];
+ for (p = (char_u *)incl_regmatch.endp[0];
*p && !vim_isfilec(*p); p++) {}
for (i = 0; vim_isfilec(p[i]); i++) {}
}
if (i == 0) {
// Nothing found, use the rest of the line.
- p = incl_regmatch.endp[0];
+ p = (char_u *)incl_regmatch.endp[0];
i = (int)STRLEN(p);
} else if (p > line) {
// Avoid checking before the start of the line, can
@@ -5518,7 +3610,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;
}
@@ -5530,7 +3622,6 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
}
}
}
- ui_flush(); // output each line directly
}
if (new_fname != NULL) {
@@ -5544,7 +3635,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 +3656,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,
@@ -5581,9 +3672,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
}
}
} else {
- /*
- * Check if the line is a define (type == FIND_DEFINE)
- */
+ // Check if the line is a define (type == FIND_DEFINE)
p = line;
search_line:
define_matched = false;
@@ -5592,24 +3681,21 @@ search_line:
// Pattern must be first identifier after 'define', so skip
// to that position before checking for match of pattern. Also
// don't let it match beyond the end of this identifier.
- p = def_regmatch.endp[0];
+ p = (char_u *)def_regmatch.endp[0];
while (*p && !vim_iswordc(*p)) {
p++;
}
define_matched = true;
}
- /*
- * Look for a match. Don't do this if we are looking for a
- * define and this line didn't match define_prog above.
- */
+ // Look for a match. Don't do this if we are looking for a
+ // 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) {
- matched = !mb_strnicmp(startp, ptr, len);
+ matched = !mb_strnicmp((char *)startp, (char *)ptr, len);
} else {
matched = !STRNCMP(startp, ptr, len);
}
@@ -5620,7 +3706,7 @@ search_line:
} else if (regmatch.regprog != NULL
&& vim_regexec(&regmatch, (char *)line, (colnr_T)(p - line))) {
matched = true;
- startp = regmatch.startp[0];
+ startp = (char_u *)regmatch.startp[0];
// Check if the line is not a comment line (unless we are
// looking for a define). A line starting with "# define"
// is not considered to be a comment line.
@@ -5631,16 +3717,14 @@ search_line:
matched = false;
}
- /*
- * Also check for a "/ *" or "/ /" before the match.
- * Skips lines like "int backwards; / * normal index
- * * /" when looking for "normal".
- * Note: Doesn't skip "/ *" in comments.
- */
+ // Also check for a "/ *" or "/ /" before the match.
+ // Skips lines like "int backwards; / * normal index
+ // * /" when looking for "normal".
+ // Note: Doesn't skip "/ *" in comments.
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 +3755,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 +3765,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);
@@ -5726,9 +3810,9 @@ search_line:
cont_s_ipos = true;
}
IObuff[i] = NUL;
- aux = IObuff;
+ aux = (char_u *)IObuff;
- if (i == compl_length) {
+ if (i == ins_compl_len()) {
goto exit_matched;
}
}
@@ -5754,7 +3838,7 @@ search_line:
}
if (!got_int) { // don't display if 'q' typed
// at "--more--" message
- msg_home_replace_hl(curr_fname);
+ msg_home_replace_hl((char *)curr_fname);
}
prev_fname = curr_fname;
}
@@ -5820,14 +3904,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 +3922,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;
@@ -5852,11 +3936,9 @@ exit_matched:
break;
}
- /*
- * Read the next line. When reading an included file and encountering
- * end-of-file, close the file and continue in the file that included
- * it.
- */
+ // Read the next line. When reading an included file and encountering
+ // end-of-file, close the file and continue in the file that included
+ // it.
while (depth >= 0 && !already
&& vim_fgets(line = file_line, LSIZE, files[depth].fp)) {
fclose(files[depth].fp);
@@ -5963,8 +4045,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);
- ui_flush(); // show one line at a time
+ msg_prt_line((char *)line, false);
// Definition continues until line that doesn't end with '\'
if (got_int || type != FIND_DEFINE || p < line || *p != '\\') {
@@ -5980,7 +4061,7 @@ static void show_pat_in_path(char_u *line, int type, bool did_show, int action,
if (++*lnum > curbuf->b_ml.ml_line_count) {
break;
}
- line = ml_get(*lnum);
+ line = (char_u *)ml_get(*lnum);
}
msg_putchar('\n');
}
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index daa8e99d31..c6887a2362 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -752,7 +752,7 @@ static int open_shada_file_for_reading(const char *const fname, ShaDaReadDef *sd
return error;
}
- assert(STRCMP(p_enc, "utf-8") == 0);
+ assert(strcmp(p_enc, "utf-8") == 0);
return 0;
}
@@ -882,10 +882,10 @@ static const void *shada_hist_iter(const void *const iter, const uint8_t history
.data = {
.history_item = {
.histtype = history_type,
- .string = (char *)hist_he.hisstr,
+ .string = hist_he.hisstr,
.sep = (char)(history_type == HIST_SEARCH
- ? (char)hist_he.hisstr[STRLEN(hist_he.hisstr) + 1]
- : 0),
+ ? hist_he.hisstr[STRLEN(hist_he.hisstr) + 1]
+ : 0),
.additional_elements = hist_he.additional_elements,
}
}
@@ -1008,7 +1008,7 @@ static inline void hms_to_he_array(const HistoryMergerState *const hms_p,
HMLL_FORALL(&hms_p->hmll, cur_entry, {
hist->timestamp = cur_entry->data.timestamp;
hist->hisnum = (int)(hist - hist_array) + 1;
- hist->hisstr = (char_u *)cur_entry->data.data.history_item.string;
+ hist->hisstr = cur_entry->data.data.history_item.string;
hist->additional_elements =
cur_entry->data.data.history_item.additional_elements;
hist++;
@@ -1053,7 +1053,7 @@ static buf_T *find_buffer(khash_t(fnamebufs) *const fname_bufs, const char *cons
kh_key(fname_bufs, k) = xstrdup(fname);
FOR_ALL_BUFFERS(buf) {
if (buf->b_ffname != NULL) {
- if (FNAMECMP(fname, buf->b_ffname) == 0) {
+ if (path_fnamecmp(fname, buf->b_ffname) == 0) {
kh_val(fname_bufs, k) = buf;
return buf;
}
@@ -1238,7 +1238,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
// string is close to useless: you can only use it with :& or :~ and
// that’s all because s//~ is not available until the first call to
// regtilde. Vim was not calling this for some reason.
- (void)(char *)regtilde((char_u *)cur_entry.data.sub_string.sub, p_magic, false);
+ (void)regtilde(cur_entry.data.sub_string.sub, p_magic, false);
// Do not free shada entry: its allocated memory was saved above.
break;
case kSDItemHistoryEntry:
@@ -1313,9 +1313,9 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
MERGE_JUMPS(curwin->w_jumplistlen, curwin->w_jumplist, xfmark_T,
fmark.timestamp, fmark.mark, cur_entry,
(buf == NULL
- ? (jl_entry.fname != NULL
- && STRCMP(fm.fname, jl_entry.fname) == 0)
- : fm.fmark.fnum == jl_entry.fmark.fnum),
+ ? (jl_entry.fname != NULL
+ && strcmp(fm.fname, jl_entry.fname) == 0)
+ : fm.fmark.fnum == jl_entry.fmark.fnum),
free_xfmark, SDE_TO_XFMARK, ADJUST_IDX, DUMMY_AFTERFREE);
#undef SDE_TO_XFMARK
#undef ADJUST_IDX
@@ -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]);
}
}
@@ -2378,7 +2378,7 @@ static inline void add_search_pattern(PossiblyFreedShadaEntry *const ret_pse,
static inline void shada_initialize_registers(WriteMergerState *const wms, int max_reg_lines)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE
{
- const void *reg_iter = NULL;
+ iter_register_T reg_iter = ITER_REGISTER_NULL;
const bool limit_reg_lines = max_reg_lines >= 0;
do {
yankreg_T reg;
@@ -2409,7 +2409,7 @@ static inline void shada_initialize_registers(WriteMergerState *const wms, int m
}
}
};
- } while (reg_iter != NULL);
+ } while (reg_iter != ITER_REGISTER_NULL);
}
/// Replace numbered mark in WriteMergerState
@@ -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) {
@@ -3098,7 +3098,7 @@ shada_write_file_nomerge: {}
}
}
#endif
- if (vim_rename((char_u *)tempname, (char_u *)fname) == -1) {
+ if (vim_rename(tempname, fname) == -1) {
semsg(_(RNERR "Can't rename ShaDa file from %s to %s!"),
tempname, fname);
} else {
@@ -3996,12 +3996,12 @@ 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);
size_t n = STRLEN(NameBuff);
- if (mb_strnicmp((char_u *)NameBuff, (char_u *)new_name, n) == 0) {
+ if (mb_strnicmp(NameBuff, new_name, n) == 0) {
retval = true;
break;
}
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index f1ddbfd147..ed546cf303 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -26,11 +26,11 @@
typedef struct sign sign_T;
struct sign {
- sign_T *sn_next; // next sign in list
+ sign_T *sn_next; // next sign in list
int sn_typenr; // type number of sign
- char_u *sn_name; // name of sign
- char_u *sn_icon; // name of pixmap
- char_u *sn_text; // text used instead of pixmap
+ char *sn_name; // name of sign
+ char *sn_icon; // name of pixmap
+ char *sn_text; // text used instead of pixmap
int sn_line_hl; // highlight ID for line
int sn_text_hl; // highlight ID for text
int sn_cul_hl; // highlight ID for text on current line when 'cursorline' is set
@@ -71,14 +71,13 @@ void init_signs(void)
/// A new sign in group 'groupname' is added. If the group is not present,
/// create it. Otherwise reference the group.
-///
-static signgroup_T *sign_group_ref(const char_u *groupname)
+static signgroup_T *sign_group_ref(const char *groupname)
{
hash_T hash;
hashitem_T *hi;
signgroup_T *group;
- hash = hash_hash(groupname);
+ hash = hash_hash((char_u *)groupname);
hi = hash_lookup(&sg_table, (char *)groupname, STRLEN(groupname), hash);
if (HASHITEM_EMPTY(hi)) {
// new group
@@ -87,7 +86,7 @@ static signgroup_T *sign_group_ref(const char_u *groupname)
STRCPY(group->sg_name, groupname);
group->sg_refcount = 1;
group->sg_next_sign_id = 1;
- hash_add_item(&sg_table, hi, group->sg_name, hash);
+ hash_add_item(&sg_table, hi, (char_u *)group->sg_name, hash);
} else {
// existing group
group = HI2SG(hi);
@@ -99,11 +98,11 @@ static signgroup_T *sign_group_ref(const char_u *groupname)
/// A sign in group 'groupname' is removed. If all the signs in this group are
/// removed, then remove the group.
-static void sign_group_unref(char_u *groupname)
+static void sign_group_unref(char *groupname)
{
signgroup_T *group;
- hashitem_T *hi = hash_find(&sg_table, (char *)groupname);
+ hashitem_T *hi = hash_find(&sg_table, groupname);
if (!HASHITEM_EMPTY(hi)) {
group = HI2SG(hi);
group->sg_refcount--;
@@ -118,16 +117,16 @@ static void sign_group_unref(char_u *groupname)
/// @return true if 'sign' is in 'group'.
/// A sign can either be in the global group (sign->group == NULL)
/// or in a named group. If 'group' is '*', then the sign is part of the group.
-static bool sign_in_group(sign_entry_T *sign, const char_u *group)
+static bool sign_in_group(sign_entry_T *sign, const char *group)
{
- return ((group != NULL && STRCMP(group, "*") == 0)
+ return ((group != NULL && strcmp(group, "*") == 0)
|| (group == NULL && sign->se_group == NULL)
|| (group != NULL && sign->se_group != NULL
- && STRCMP(group, sign->se_group->sg_name) == 0));
+ && strcmp(group, sign->se_group->sg_name) == 0));
}
/// Get the next free sign identifier in the specified group
-static int sign_group_get_next_signid(buf_T *buf, const char_u *groupname)
+static int sign_group_get_next_signid(buf_T *buf, const char *groupname)
{
int id = 1;
signgroup_T *group = NULL;
@@ -154,7 +153,7 @@ static int sign_group_get_next_signid(buf_T *buf, const char_u *groupname)
// Check whether this sign is already placed in the buffer
found = true;
FOR_ALL_SIGNS_IN_BUF(buf, sign) {
- if (id == sign->se_id && sign_in_group(sign, groupname)) {
+ if (id == sign->se_id && sign_in_group(sign, (char *)groupname)) {
found = false; // sign identifier is in use
break;
}
@@ -177,7 +176,7 @@ static int sign_group_get_next_signid(buf_T *buf, const char_u *groupname)
/// @param typenr typenr of sign we are adding
/// @param has_text_or_icon sign has text or icon
static void insert_sign(buf_T *buf, sign_entry_T *prev, sign_entry_T *next, int id,
- const char_u *group, int prio, linenr_T lnum, int typenr,
+ const char *group, int prio, linenr_T lnum, int typenr,
bool has_text_or_icon)
{
sign_entry_T *newsign = xmalloc(sizeof(sign_entry_T));
@@ -203,7 +202,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();
}
@@ -224,7 +223,7 @@ static void insert_sign(buf_T *buf, sign_entry_T *prev, sign_entry_T *next, int
/// @param lnum line number which gets the mark
/// @param typenr typenr of sign we are adding
/// @param has_text_or_icon sign has text or icon
-static void insert_sign_by_lnum_prio(buf_T *buf, sign_entry_T *prev, int id, const char_u *group,
+static void insert_sign_by_lnum_prio(buf_T *buf, sign_entry_T *prev, int id, const char *group,
int prio, linenr_T lnum, int typenr, bool has_text_or_icon)
{
sign_entry_T *sign;
@@ -259,7 +258,7 @@ static sign_T *find_sign_by_typenr(int typenr)
}
/// Get the name of a sign by its typenr.
-static char_u *sign_typenr2name(int typenr)
+static char *sign_typenr2name(int typenr)
{
sign_T *sp;
@@ -268,7 +267,7 @@ static char_u *sign_typenr2name(int typenr)
return sp->sn_name;
}
}
- return (char_u *)_("[Deleted]");
+ return _("[Deleted]");
}
/// Return information about a sign in a Dict
@@ -280,7 +279,7 @@ static dict_T *sign_get_info(sign_entry_T *sign)
? (char *)""
: (char *)sign->se_group->sg_name));
tv_dict_add_nr(d, S_LEN("lnum"), sign->se_lnum);
- tv_dict_add_str(d, S_LEN("name"), (char *)sign_typenr2name(sign->se_typenr));
+ tv_dict_add_str(d, S_LEN("name"), sign_typenr2name(sign->se_typenr));
tv_dict_add_nr(d, S_LEN("priority"), sign->se_priority);
return d;
@@ -369,7 +368,7 @@ static void sign_sort_by_prio_on_line(buf_T *buf, sign_entry_T *sign)
/// @param lnum line number which gets the mark
/// @param typenr typenr of sign we are adding
/// @param has_text_or_icon sign has text or icon
-static void buf_addsign(buf_T *buf, int id, const char_u *groupname, int prio, linenr_T lnum,
+static void buf_addsign(buf_T *buf, int id, const char *groupname, int prio, linenr_T lnum,
int typenr, bool has_text_or_icon)
{
sign_entry_T *sign; // a sign in the signlist
@@ -416,13 +415,13 @@ static void buf_addsign(buf_T *buf, int id, const char_u *groupname, int prio, l
/// @param group sign group
/// @param typenr typenr of sign we are adding
/// @param prio sign priority
-static linenr_T buf_change_sign_type(buf_T *buf, int markId, const char_u *group, int typenr,
+static linenr_T buf_change_sign_type(buf_T *buf, int markId, const char *group, int typenr,
int prio)
{
sign_entry_T *sign; // a sign in the signlist
FOR_ALL_SIGNS_IN_BUF(buf, sign) {
- if (sign->se_id == markId && sign_in_group(sign, group)) {
+ if (sign->se_id == markId && sign_in_group(sign, (char *)group)) {
sign->se_typenr = typenr;
sign->se_priority = prio;
sign_sort_by_prio_on_line(buf, sign);
@@ -534,7 +533,7 @@ int buf_get_signattrs(buf_T *buf, linenr_T lnum, SignTextAttrs sattrs[], HlPriAt
///
/// @return the line number of the deleted sign. If multiple signs are deleted,
/// then returns the line number of the last sign deleted.
-static linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char_u *group)
+static linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char *group)
{
sign_entry_T **lastp; // pointer to pointer to current sign
sign_entry_T *sign; // a sign in a b_signlist
@@ -555,7 +554,7 @@ static linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char_u *group)
lnum = sign->se_lnum;
buf_signcols_del_check(buf, lnum, lnum);
if (sign->se_group != NULL) {
- sign_group_unref(sign->se_group->sg_name);
+ sign_group_unref((char *)sign->se_group->sg_name);
}
xfree(sign);
redraw_buf_line_later(buf, lnum);
@@ -576,7 +575,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();
}
@@ -590,7 +589,7 @@ static linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char_u *group)
/// @param buf buffer to store sign in
/// @param id sign ID
/// @param group sign group
-static int buf_findsign(buf_T *buf, int id, char_u *group)
+static int buf_findsign(buf_T *buf, int id, char *group)
{
sign_entry_T *sign; // a sign in the signlist
@@ -609,7 +608,7 @@ static int buf_findsign(buf_T *buf, int id, char_u *group)
/// @param buf buffer whose sign we are searching for
/// @param lnum line number of sign
/// @param groupname sign group name
-static sign_entry_T *buf_getsign_at_line(buf_T *buf, linenr_T lnum, char_u *groupname)
+static sign_entry_T *buf_getsign_at_line(buf_T *buf, linenr_T lnum, char *groupname)
{
sign_entry_T *sign; // a sign in the signlist
@@ -633,7 +632,7 @@ static sign_entry_T *buf_getsign_at_line(buf_T *buf, linenr_T lnum, char_u *grou
/// @param buf buffer whose sign we are searching for
/// @param lnum line number of sign
/// @param groupname sign group name
-static int buf_findsign_id(buf_T *buf, linenr_T lnum, char_u *groupname)
+static int buf_findsign_id(buf_T *buf, linenr_T lnum, char *groupname)
{
sign_entry_T *sign; // a sign in the signlist
@@ -661,13 +660,13 @@ void buf_delete_signs(buf_T *buf, char *group)
lastp = &buf->b_signlist;
for (sign = buf->b_signlist; sign != NULL; sign = next) {
next = sign->se_next;
- if (sign_in_group(sign, (char_u *)group)) {
+ if (sign_in_group(sign, group)) {
*lastp = next;
if (next != NULL) {
next->se_prev = sign->se_prev;
}
if (sign->se_group != NULL) {
- sign_group_unref(sign->se_group->sg_name);
+ sign_group_unref((char *)sign->se_group->sg_name);
}
xfree(sign);
} else {
@@ -678,7 +677,7 @@ void buf_delete_signs(buf_T *buf, char *group)
}
/// List placed signs for "rbuf". If "rbuf" is NULL do it for all buffers.
-static void sign_list_placed(buf_T *rbuf, char_u *sign_group)
+static void sign_list_placed(buf_T *rbuf, char *sign_group)
{
buf_T *buf;
sign_entry_T *sign;
@@ -778,14 +777,14 @@ void sign_mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T
///
/// @param begin_cmd begin of sign subcmd
/// @param end_cmd just after sign subcmd
-static int sign_cmd_idx(char_u *begin_cmd, char_u *end_cmd)
+static int sign_cmd_idx(char *begin_cmd, char *end_cmd)
{
int idx;
- char_u save = *end_cmd;
+ char save = *end_cmd;
- *end_cmd = (char_u)NUL;
+ *end_cmd = NUL;
for (idx = 0;; idx++) {
- if (cmds[idx] == NULL || STRCMP(begin_cmd, cmds[idx]) == 0) {
+ if (cmds[idx] == NULL || strcmp(begin_cmd, cmds[idx]) == 0) {
break;
}
}
@@ -794,7 +793,7 @@ static int sign_cmd_idx(char_u *begin_cmd, char_u *end_cmd)
}
/// Find a sign by name. Also returns pointer to the previous sign.
-static sign_T *sign_find(const char_u *name, sign_T **sp_prev)
+static sign_T *sign_find(const char *name, sign_T **sp_prev)
{
sign_T *sp;
@@ -802,7 +801,7 @@ static sign_T *sign_find(const char_u *name, sign_T **sp_prev)
*sp_prev = NULL;
}
for (sp = first_sign; sp != NULL; sp = sp->sn_next) {
- if (STRCMP(sp->sn_name, name) == 0) {
+ if (strcmp(sp->sn_name, name) == 0) {
break;
}
if (sp_prev != NULL) {
@@ -814,7 +813,7 @@ static sign_T *sign_find(const char_u *name, sign_T **sp_prev)
}
/// Allocate a new sign
-static sign_T *alloc_new_sign(char_u *name)
+static sign_T *alloc_new_sign(char *name)
{
sign_T *sp;
sign_T *lp;
@@ -848,24 +847,24 @@ static sign_T *alloc_new_sign(char_u *name)
next_sign_typenr = 1; // wrap around
}
- sp->sn_name = vim_strsave(name);
+ sp->sn_name = xstrdup(name);
return sp;
}
/// Initialize the icon information for a new sign
-static void sign_define_init_icon(sign_T *sp, char_u *icon)
+static void sign_define_init_icon(sign_T *sp, char *icon)
{
xfree(sp->sn_icon);
- sp->sn_icon = vim_strsave(icon);
+ sp->sn_icon = xstrdup(icon);
backslash_halve(sp->sn_icon);
}
/// Initialize the text for a new sign
-static int sign_define_init_text(sign_T *sp, char_u *text)
+static int sign_define_init_text(sign_T *sp, char *text)
{
- char_u *s;
- char_u *endp;
+ char *s;
+ char *endp;
int cells;
size_t len;
@@ -880,11 +879,11 @@ static int sign_define_init_text(sign_T *sp, char_u *text)
}
// Count cells and check for non-printable chars
cells = 0;
- for (s = text; s < endp; s += utfc_ptr2len((char *)s)) {
- if (!vim_isprintc(utf_ptr2char((char *)s))) {
+ for (s = text; s < endp; s += utfc_ptr2len(s)) {
+ if (!vim_isprintc(utf_ptr2char(s))) {
break;
}
- cells += utf_ptr2cells((char *)s);
+ cells += utf_ptr2cells(s);
}
// Currently must be empty, one or two display cells
if (s != endp || cells > 2) {
@@ -900,7 +899,7 @@ static int sign_define_init_text(sign_T *sp, char_u *text)
// Allocate one byte more if we need to pad up
// with a space.
len = (size_t)(endp - text + ((cells == 1) ? 1 : 0));
- sp->sn_text = vim_strnsave(text, len);
+ sp->sn_text = xstrnsave(text, len);
if (cells == 1) {
STRCPY(sp->sn_text + len - 1, " ");
@@ -910,8 +909,8 @@ static int sign_define_init_text(sign_T *sp, char_u *text)
}
/// Define a new sign or update an existing sign
-static int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text,
- char_u *texthl, char_u *culhl, char *numhl)
+static int sign_define_by_name(char *name, char *icon, char *linehl, char *text, char *texthl,
+ char *culhl, char *numhl)
{
sign_T *sp_prev;
sign_T *sp;
@@ -934,7 +933,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);
}
}
}
@@ -952,7 +951,7 @@ static int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_
if (*linehl == NUL) {
sp->sn_line_hl = 0;
} else {
- sp->sn_line_hl = syn_check_group((char *)linehl, STRLEN(linehl));
+ sp->sn_line_hl = syn_check_group(linehl, STRLEN(linehl));
}
}
@@ -960,7 +959,7 @@ static int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_
if (*texthl == NUL) {
sp->sn_text_hl = 0;
} else {
- sp->sn_text_hl = syn_check_group((char *)texthl, STRLEN(texthl));
+ sp->sn_text_hl = syn_check_group(texthl, STRLEN(texthl));
}
}
@@ -968,7 +967,7 @@ static int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_
if (*culhl == NUL) {
sp->sn_cul_hl = 0;
} else {
- sp->sn_cul_hl = syn_check_group((char *)culhl, STRLEN(culhl));
+ sp->sn_cul_hl = syn_check_group(culhl, STRLEN(culhl));
}
}
@@ -984,7 +983,7 @@ static int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_
}
/// Free the sign specified by 'name'.
-static int sign_undefine_by_name(const char_u *name)
+static int sign_undefine_by_name(const char *name)
{
sign_T *sp_prev;
sign_T *sp;
@@ -1000,7 +999,7 @@ static int sign_undefine_by_name(const char_u *name)
}
/// List the signs matching 'name'
-static void sign_list_by_name(char_u *name)
+static void sign_list_by_name(char *name)
{
sign_T *sp;
@@ -1024,7 +1023,7 @@ static void may_force_numberwidth_recompute(buf_T *buf, int unplace)
}
/// Place a sign at the specified file location or update a sign.
-static int sign_place(int *sign_id, const char_u *sign_group, const char_u *sign_name, buf_T *buf,
+static int sign_place(int *sign_id, const char *sign_group, const char *sign_name, buf_T *buf,
linenr_T lnum, int prio)
{
sign_T *sp;
@@ -1035,7 +1034,7 @@ static int sign_place(int *sign_id, const char_u *sign_group, const char_u *sign
}
for (sp = first_sign; sp != NULL; sp = sp->sn_next) {
- if (STRCMP(sp->sn_name, sign_name) == 0) {
+ if (strcmp(sp->sn_name, sign_name) == 0) {
break;
}
}
@@ -1044,7 +1043,7 @@ static int sign_place(int *sign_id, const char_u *sign_group, const char_u *sign
return FAIL;
}
if (*sign_id == 0) {
- *sign_id = sign_group_get_next_signid(buf, sign_group);
+ *sign_id = sign_group_get_next_signid(buf, (char *)sign_group);
}
if (lnum > 0) {
@@ -1053,14 +1052,14 @@ static int sign_place(int *sign_id, const char_u *sign_group, const char_u *sign
bool has_text_or_icon = sp->sn_text != NULL || sp->sn_icon != NULL;
buf_addsign(buf,
*sign_id,
- sign_group,
+ (char *)sign_group,
prio,
lnum,
sp->sn_typenr,
has_text_or_icon);
} else {
// ":sign place {id} file={fname}": change sign type and/or priority
- lnum = buf_change_sign_type(buf, *sign_id, sign_group, sp->sn_typenr, prio);
+ lnum = buf_change_sign_type(buf, *sign_id, (char *)sign_group, sp->sn_typenr, prio);
}
if (lnum > 0) {
redraw_buf_line_later(buf, lnum);
@@ -1077,15 +1076,15 @@ static int sign_place(int *sign_id, const char_u *sign_group, const char_u *sign
}
/// Unplace the specified sign
-static int sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T atlnum)
+static int sign_unplace(int sign_id, char *sign_group, buf_T *buf, linenr_T atlnum)
{
if (buf->b_signlist == NULL) { // No signs in the buffer
return OK;
}
if (sign_id == 0) {
// Delete all the signs in the specified buffer
- redraw_buf_later(buf, NOT_VALID);
- buf_delete_signs(buf, (char *)sign_group);
+ redraw_buf_later(buf, UPD_NOT_VALID);
+ buf_delete_signs(buf, sign_group);
} else {
linenr_T lnum;
@@ -1108,7 +1107,7 @@ static int sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T at
}
/// Unplace the sign at the current cursor line.
-static void sign_unplace_at_cursor(char_u *groupname)
+static void sign_unplace_at_cursor(char *groupname)
{
int id = -1;
@@ -1121,7 +1120,7 @@ static void sign_unplace_at_cursor(char_u *groupname)
}
/// Jump to a sign.
-static linenr_T sign_jump(int sign_id, char_u *sign_group, buf_T *buf)
+static linenr_T sign_jump(int sign_id, char *sign_group, buf_T *buf)
{
linenr_T lnum;
@@ -1154,49 +1153,49 @@ static linenr_T sign_jump(int sign_id, char_u *sign_group, buf_T *buf)
}
/// ":sign define {name} ..." command
-static void sign_define_cmd(char_u *sign_name, char_u *cmdline)
-{
- char_u *arg;
- char_u *p = cmdline;
- char_u *icon = NULL;
- char_u *text = NULL;
- char_u *linehl = NULL;
- char_u *texthl = NULL;
- char_u *culhl = NULL;
- char_u *numhl = NULL;
+static void sign_define_cmd(char *sign_name, char *cmdline)
+{
+ char *arg;
+ char *p = cmdline;
+ char *icon = NULL;
+ char *text = NULL;
+ char *linehl = NULL;
+ char *texthl = NULL;
+ char *culhl = NULL;
+ char *numhl = NULL;
int failed = false;
// set values for a defined sign.
for (;;) {
- arg = (char_u *)skipwhite((char *)p);
+ arg = skipwhite(p);
if (*arg == NUL) {
break;
}
- p = (char_u *)skiptowhite_esc((char *)arg);
+ p = skiptowhite_esc(arg);
if (STRNCMP(arg, "icon=", 5) == 0) {
arg += 5;
XFREE_CLEAR(icon);
- icon = vim_strnsave(arg, (size_t)(p - arg));
+ icon = xstrnsave(arg, (size_t)(p - arg));
} else if (STRNCMP(arg, "text=", 5) == 0) {
arg += 5;
XFREE_CLEAR(text);
- text = vim_strnsave(arg, (size_t)(p - arg));
+ text = xstrnsave(arg, (size_t)(p - arg));
} else if (STRNCMP(arg, "linehl=", 7) == 0) {
arg += 7;
XFREE_CLEAR(linehl);
- linehl = vim_strnsave(arg, (size_t)(p - arg));
+ linehl = xstrnsave(arg, (size_t)(p - arg));
} else if (STRNCMP(arg, "texthl=", 7) == 0) {
arg += 7;
XFREE_CLEAR(texthl);
- texthl = vim_strnsave(arg, (size_t)(p - arg));
+ texthl = xstrnsave(arg, (size_t)(p - arg));
} else if (STRNCMP(arg, "culhl=", 6) == 0) {
arg += 6;
XFREE_CLEAR(culhl);
- culhl = vim_strnsave(arg, (size_t)(p - arg));
+ culhl = xstrnsave(arg, (size_t)(p - arg));
} else if (STRNCMP(arg, "numhl=", 6) == 0) {
arg += 6;
XFREE_CLEAR(numhl);
- numhl = vim_strnsave(arg, (size_t)(p - arg));
+ numhl = xstrnsave(arg, (size_t)(p - arg));
} else {
semsg(_(e_invarg2), arg);
failed = true;
@@ -1205,7 +1204,8 @@ static void sign_define_cmd(char_u *sign_name, char_u *cmdline)
}
if (!failed) {
- sign_define_by_name(sign_name, icon, linehl, text, texthl, culhl, (char *)numhl);
+ sign_define_by_name(sign_name, icon, linehl, text,
+ texthl, culhl, numhl);
}
xfree(icon);
@@ -1217,7 +1217,7 @@ static void sign_define_cmd(char_u *sign_name, char_u *cmdline)
}
/// ":sign place" command
-static void sign_place_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id, char_u *group,
+static void sign_place_cmd(buf_T *buf, linenr_T lnum, char *sign_name, int id, char *group,
int prio)
{
if (id <= 0) {
@@ -1250,7 +1250,7 @@ static void sign_place_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id,
}
/// ":sign unplace" command
-static void sign_unplace_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id, char_u *group)
+static void sign_unplace_cmd(buf_T *buf, linenr_T lnum, char *sign_name, int id, char *group)
{
if (lnum >= 0 || sign_name != NULL || (group != NULL && *group == '\0')) {
emsg(_(e_invarg));
@@ -1272,7 +1272,7 @@ static void sign_unplace_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int i
// :sign unplace * group=*
FOR_ALL_BUFFERS(cbuf) {
if (cbuf->b_signlist != NULL) {
- buf_delete_signs(cbuf, (char *)group);
+ buf_delete_signs(cbuf, group);
}
}
}
@@ -1307,7 +1307,7 @@ static void sign_unplace_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int i
/// :sign jump {id} buffer={nr}
/// :sign jump {id} group={group} file={fname}
/// :sign jump {id} group={group} buffer={nr}
-static void sign_jump_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id, char_u *group)
+static void sign_jump_cmd(buf_T *buf, linenr_T lnum, char *sign_name, int id, char *group)
{
if (sign_name == NULL && group == NULL && id == -1) {
emsg(_(e_argreq));
@@ -1329,30 +1329,30 @@ static void sign_jump_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id,
/// ":sign jump" commands.
/// The supported arguments are: line={lnum} name={name} group={group}
/// priority={prio} and file={fname} or buffer={nr}.
-static int parse_sign_cmd_args(int cmd, char_u *arg, char_u **sign_name, int *signid,
- char_u **group, int *prio, buf_T **buf, linenr_T *lnum)
+static int parse_sign_cmd_args(int cmd, char *arg, char **sign_name, int *signid, char **group,
+ int *prio, buf_T **buf, linenr_T *lnum)
{
- char_u *arg1;
- char_u *name;
- char_u *filename = NULL;
+ char *arg1;
+ char *name;
+ char *filename = NULL;
int lnum_arg = false;
// first arg could be placed sign id
arg1 = arg;
if (ascii_isdigit(*arg)) {
- *signid = getdigits_int((char **)&arg, true, 0);
+ *signid = getdigits_int(&arg, true, 0);
if (!ascii_iswhite(*arg) && *arg != NUL) {
*signid = -1;
arg = arg1;
} else {
- arg = (char_u *)skipwhite((char *)arg);
+ arg = skipwhite(arg);
}
}
while (*arg != NUL) {
if (STRNCMP(arg, "line=", 5) == 0) {
arg += 5;
- *lnum = atoi((char *)arg);
+ *lnum = atoi(arg);
arg = skiptowhite(arg);
lnum_arg = true;
} else if (STRNCMP(arg, "*", 1) == 0 && cmd == SIGNCMD_UNPLACE) {
@@ -1382,18 +1382,18 @@ static int parse_sign_cmd_args(int cmd, char_u *arg, char_u **sign_name, int *si
}
} else if (STRNCMP(arg, "priority=", 9) == 0) {
arg += 9;
- *prio = atoi((char *)arg);
+ *prio = atoi(arg);
arg = skiptowhite(arg);
} else if (STRNCMP(arg, "file=", 5) == 0) {
arg += 5;
filename = arg;
- *buf = buflist_findname_exp((char *)arg);
+ *buf = buflist_findname_exp(arg);
break;
} else if (STRNCMP(arg, "buffer=", 7) == 0) {
arg += 7;
filename = arg;
- *buf = buflist_findnr(getdigits_int((char **)&arg, true, 0));
- if (*skipwhite((char *)arg) != NUL) {
+ *buf = buflist_findnr(getdigits_int(&arg, true, 0));
+ if (*skipwhite(arg) != NUL) {
semsg(_(e_trailing_arg), arg);
}
break;
@@ -1401,7 +1401,7 @@ static int parse_sign_cmd_args(int cmd, char_u *arg, char_u **sign_name, int *si
emsg(_(e_invarg));
return FAIL;
}
- arg = (char_u *)skipwhite((char *)arg);
+ arg = skipwhite(arg);
}
if (filename != NULL && *buf == NULL) {
@@ -1421,8 +1421,8 @@ static int parse_sign_cmd_args(int cmd, char_u *arg, char_u **sign_name, int *si
/// ":sign" command
void ex_sign(exarg_T *eap)
{
- char_u *arg = (char_u *)eap->arg;
- char_u *p;
+ char *arg = eap->arg;
+ char *p;
int idx;
sign_T *sp;
@@ -1433,7 +1433,7 @@ void ex_sign(exarg_T *eap)
semsg(_("E160: Unknown sign command: %s"), arg);
return;
}
- arg = (char_u *)skipwhite((char *)p);
+ arg = skipwhite(p);
if (idx <= SIGNCMD_LIST) {
// Define, undefine or list signs.
@@ -1445,7 +1445,7 @@ void ex_sign(exarg_T *eap)
} else if (*arg == NUL) {
emsg(_("E156: Missing sign name"));
} else {
- char_u *name;
+ char *name;
// Isolate the sign name. If it's a number skip leading zeroes,
// so that "099" and "99" are the same sign. But keep "0".
@@ -1456,7 +1456,7 @@ void ex_sign(exarg_T *eap)
while (arg[0] == '0' && arg[1] != NUL) {
arg++;
}
- name = vim_strsave(arg);
+ name = xstrdup(arg);
if (idx == SIGNCMD_DEFINE) {
sign_define_cmd(name, p);
@@ -1474,8 +1474,8 @@ void ex_sign(exarg_T *eap)
} else {
int id = -1;
linenr_T lnum = -1;
- char_u *sign_name = NULL;
- char_u *group = NULL;
+ char *sign_name = NULL;
+ char *group = NULL;
int prio = SIGN_DEF_PRIO;
buf_T *buf = NULL;
@@ -1500,12 +1500,12 @@ static void sign_getinfo(sign_T *sp, dict_T *retdict)
{
const char *p;
- tv_dict_add_str(retdict, S_LEN("name"), (char *)sp->sn_name);
+ tv_dict_add_str(retdict, S_LEN("name"), sp->sn_name);
if (sp->sn_icon != NULL) {
- tv_dict_add_str(retdict, S_LEN("icon"), (char *)sp->sn_icon);
+ tv_dict_add_str(retdict, S_LEN("icon"), sp->sn_icon);
}
if (sp->sn_text != NULL) {
- tv_dict_add_str(retdict, S_LEN("text"), (char *)sp->sn_text);
+ tv_dict_add_str(retdict, S_LEN("text"), sp->sn_text);
}
if (sp->sn_line_hl > 0) {
p = get_highlight_name_ext(NULL, sp->sn_line_hl - 1, false);
@@ -1539,13 +1539,13 @@ static void sign_getinfo(sign_T *sp, dict_T *retdict)
/// If 'name' is NULL, return a list of all the defined signs.
/// Otherwise, return information about the specified sign.
-static void sign_getlist(const char_u *name, list_T *retlist)
+static void sign_getlist(const char *name, list_T *retlist)
{
sign_T *sp = first_sign;
dict_T *dict;
if (name != NULL) {
- sp = sign_find(name, NULL);
+ sp = sign_find((char *)name, NULL);
if (sp == NULL) {
return;
}
@@ -1577,8 +1577,8 @@ list_T *get_buffer_signs(buf_T *buf)
return l;
}
-/// Return information about all the signs placed in a buffer
-static void sign_get_placed_in_buf(buf_T *buf, linenr_T lnum, int sign_id, const char_u *sign_group,
+/// @return information about all the signs placed in a buffer
+static void sign_get_placed_in_buf(buf_T *buf, linenr_T lnum, int sign_id, const char *sign_group,
list_T *retlist)
{
dict_T *d;
@@ -1594,7 +1594,7 @@ static void sign_get_placed_in_buf(buf_T *buf, linenr_T lnum, int sign_id, const
tv_dict_add_list(d, S_LEN("signs"), l);
FOR_ALL_SIGNS_IN_BUF(buf, sign) {
- if (!sign_in_group(sign, sign_group)) {
+ if (!sign_in_group(sign, (char *)sign_group)) {
continue;
}
if ((lnum == 0 && sign_id == 0)
@@ -1609,7 +1609,7 @@ static void sign_get_placed_in_buf(buf_T *buf, linenr_T lnum, int sign_id, const
/// Get a list of signs placed in buffer 'buf'. If 'num' is non-zero, return the
/// sign placed at the line number. If 'lnum' is zero, return all the signs
/// placed in 'buf'. If 'buf' is NULL, return signs placed in all the buffers.
-static void sign_get_placed(buf_T *buf, linenr_T lnum, int sign_id, const char_u *sign_group,
+static void sign_get_placed(buf_T *buf, linenr_T lnum, int sign_id, const char *sign_group,
list_T *retlist)
{
if (buf != NULL) {
@@ -1629,12 +1629,12 @@ static void sign_list_defined(sign_T *sp)
smsg("sign %s", sp->sn_name);
if (sp->sn_icon != NULL) {
msg_puts(" icon=");
- msg_outtrans((char *)sp->sn_icon);
+ msg_outtrans(sp->sn_icon);
msg_puts(_(" (not supported)"));
}
if (sp->sn_text != NULL) {
msg_puts(" text=");
- msg_outtrans((char *)sp->sn_text);
+ msg_outtrans(sp->sn_text);
}
if (sp->sn_line_hl > 0) {
msg_puts(" linehl=");
@@ -1710,8 +1710,8 @@ static enum {
EXP_SIGN_GROUPS, // expand with name of placed sign groups
} expand_what;
-// Return the n'th sign name (used for command line completion)
-static char_u *get_nth_sign_name(int idx)
+/// @return the n'th sign name (used for command line completion)
+static char *get_nth_sign_name(int idx)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
// Complete with name of signs already defined
@@ -1724,8 +1724,8 @@ static char_u *get_nth_sign_name(int idx)
return NULL;
}
-// Return the n'th sign group name (used for command line completion)
-static char_u *get_nth_sign_group_name(int idx)
+/// @return the n'th sign group name (used for command line completion)
+static char *get_nth_sign_group_name(int idx)
{
// Complete with name of sign groups already defined
int current_idx = 0;
@@ -1735,7 +1735,7 @@ static char_u *get_nth_sign_group_name(int idx)
todo--;
if (current_idx++ == idx) {
signgroup_T *const group = HI2SG(hi);
- return group->sg_name;
+ return (char *)group->sg_name;
}
}
}
@@ -1768,26 +1768,26 @@ char *get_sign_name(expand_T *xp, int idx)
return unplace_arg[idx];
}
case EXP_SIGN_NAMES:
- return (char *)get_nth_sign_name(idx);
+ return get_nth_sign_name(idx);
case EXP_SIGN_GROUPS:
- return (char *)get_nth_sign_group_name(idx);
+ return get_nth_sign_group_name(idx);
default:
return NULL;
}
}
/// Handle command line completion for :sign command.
-void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
+void set_context_in_sign_cmd(expand_T *xp, char *arg)
{
- char_u *end_subcmd;
- char_u *last;
+ char *end_subcmd;
+ char *last;
int cmd_idx;
- char_u *begin_subcmd_args;
+ char *begin_subcmd_args;
// Default: expand subcommands.
xp->xp_context = EXPAND_SIGN;
expand_what = EXP_SUBCMD;
- xp->xp_pattern = (char *)arg;
+ xp->xp_pattern = arg;
end_subcmd = skiptowhite(arg);
if (*end_subcmd == NUL) {
@@ -1801,7 +1801,7 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
// :sign {subcmd} {subcmd_args}
// |
// begin_subcmd_args
- begin_subcmd_args = (char_u *)skipwhite((char *)end_subcmd);
+ begin_subcmd_args = skipwhite(end_subcmd);
// Expand last argument of subcmd.
//
@@ -1810,21 +1810,21 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
// p
// Loop until reaching last argument.
- char_u *p = begin_subcmd_args;
+ char *p = begin_subcmd_args;
do {
- p = (char_u *)skipwhite((char *)p);
+ p = skipwhite(p);
last = p;
p = skiptowhite(p);
} while (*p != NUL);
- p = (char_u *)vim_strchr((char *)last, '=');
+ p = vim_strchr(last, '=');
// :sign define {name} {args}... {last}=
// | |
// last p
if (p == NULL) {
// Expand last argument name (before equal sign).
- xp->xp_pattern = (char *)last;
+ xp->xp_pattern = last;
switch (cmd_idx) {
case SIGNCMD_DEFINE:
expand_what = EXP_DEFINE;
@@ -1854,7 +1854,7 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg)
}
} else {
// Expand last argument value (after equal sign).
- xp->xp_pattern = (char *)p + 1;
+ xp->xp_pattern = p + 1;
switch (cmd_idx) {
case SIGNCMD_DEFINE:
if (STRNCMP(last, "texthl", 6) == 0
@@ -1928,8 +1928,8 @@ static int sign_define_from_dict(const char *name_arg, dict_T *dict)
numhl = tv_dict_get_string(dict, "numhl", true);
}
- if (sign_define_by_name((char_u *)name, (char_u *)icon, (char_u *)linehl,
- (char_u *)text, (char_u *)texthl, (char_u *)culhl, numhl)
+ if (sign_define_by_name(name, icon, linehl,
+ text, texthl, culhl, numhl)
== OK) {
retval = 0;
}
@@ -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;
@@ -2005,11 +2005,11 @@ void f_sign_getdefined(typval_T *argvars, typval_T *rettv, FunPtr fptr)
name = tv_get_string(&argvars[0]);
}
- sign_getlist((const char_u *)name, rettv->vval.v_list);
+ sign_getlist(name, rettv->vval.v_list);
}
/// "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;
@@ -2062,12 +2062,11 @@ void f_sign_getplaced(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
- sign_get_placed(buf, lnum, sign_id, (const char_u *)group,
- rettv->vval.v_list);
+ sign_get_placed(buf, lnum, sign_id, group, rettv->vval.v_list);
}
/// "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;
@@ -2103,7 +2102,7 @@ void f_sign_jump(typval_T *argvars, typval_T *rettv, FunPtr fptr)
goto cleanup;
}
- rettv->vval.v_number = sign_jump(sign_id, (char_u *)sign_group, buf);
+ rettv->vval.v_number = sign_jump(sign_id, sign_group, buf);
cleanup:
xfree(sign_group);
@@ -2115,8 +2114,8 @@ static int sign_place_from_dict(typval_T *id_tv, typval_T *group_tv, typval_T *n
typval_T *buf_tv, dict_T *dict)
{
int sign_id = 0;
- char_u *group = NULL;
- char_u *sign_name = NULL;
+ char *group = NULL;
+ char *sign_name = NULL;
buf_T *buf = NULL;
dictitem_T *di;
linenr_T lnum = 0;
@@ -2154,14 +2153,14 @@ static int sign_place_from_dict(typval_T *id_tv, typval_T *group_tv, typval_T *n
if (group_tv == NULL) {
group = NULL; // global group
} else {
- group = (char_u *)tv_get_string_chk(group_tv);
+ group = (char *)tv_get_string_chk(group_tv);
if (group == NULL) {
goto cleanup;
}
if (group[0] == '\0') { // global sign group
group = NULL;
} else {
- group = vim_strsave(group);
+ group = xstrdup(group);
}
}
@@ -2175,7 +2174,7 @@ static int sign_place_from_dict(typval_T *id_tv, typval_T *group_tv, typval_T *n
if (name_tv == NULL) {
goto cleanup;
}
- sign_name = (char_u *)tv_get_string_chk(name_tv);
+ sign_name = (char *)tv_get_string_chk(name_tv);
if (sign_name == NULL) {
goto cleanup;
}
@@ -2225,7 +2224,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 +2242,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;
@@ -2269,13 +2268,13 @@ void f_sign_placelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// Undefine multiple signs
static void sign_undefine_multiple(list_T *l, list_T *retlist)
{
- char_u *name;
+ char *name;
int retval;
TV_LIST_ITER_CONST(l, li, {
retval = -1;
- name = (char_u *)tv_get_string_chk(TV_LIST_ITEM_TV(li));
- if (name != NULL && (sign_undefine_by_name(name) == OK)) {
+ name = (char *)tv_get_string_chk(TV_LIST_ITEM_TV(li));
+ if (name != NULL && (sign_undefine_by_name((char *)name) == OK)) {
retval = 0;
}
tv_list_append_number(retlist, retval);
@@ -2283,7 +2282,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;
@@ -2308,7 +2307,7 @@ void f_sign_undefine(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
- if (sign_undefine_by_name((const char_u *)name) == OK) {
+ if (sign_undefine_by_name(name) == OK) {
rettv->vval.v_number = 0;
}
}
@@ -2321,20 +2320,20 @@ static int sign_unplace_from_dict(typval_T *group_tv, dict_T *dict)
dictitem_T *di;
int sign_id = 0;
buf_T *buf = NULL;
- char_u *group = NULL;
+ char *group = NULL;
int retval = -1;
// sign group
if (group_tv != NULL) {
- group = (char_u *)tv_get_string(group_tv);
+ group = (char *)tv_get_string(group_tv);
} else {
- group = (char_u *)tv_dict_get_string(dict, "group", false);
+ group = tv_dict_get_string(dict, "group", false);
}
if (group != NULL) {
if (group[0] == '\0') { // global sign group
group = NULL;
} else {
- group = vim_strsave(group);
+ group = xstrdup(group);
}
}
@@ -2373,7 +2372,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 +2395,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/sign_defs.h b/src/nvim/sign_defs.h
index a4fb325ec8..16e783aab7 100644
--- a/src/nvim/sign_defs.h
+++ b/src/nvim/sign_defs.h
@@ -10,9 +10,9 @@
// Sign group
typedef struct signgroup_S {
- uint16_t sg_refcount; // number of signs in this group
- int sg_next_sign_id; // next sign id for this group
- char_u sg_name[1]; // sign group name
+ uint16_t sg_refcount; // number of signs in this group
+ int sg_next_sign_id; // next sign id for this group
+ char sg_name[1]; // sign group name
} signgroup_T;
// Macros to get the sign group structure from the group name
@@ -34,7 +34,7 @@ struct sign_entry {
/// Sign attributes. Used by the screen refresh routines.
typedef struct {
- char_u *text;
+ char *text;
int hl_attr_id;
int priority;
} SignTextAttrs;
@@ -51,4 +51,4 @@ typedef enum {
SIGN_TEXT,
} SignType;
-#endif // NVIM_SIGN_DEFS_H
+#endif // NVIM_SIGN_DEFS_H
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 1e44d328b3..42891fd3fb 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -56,50 +56,60 @@
// 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/decoration.h"
+#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)
@@ -184,8 +194,8 @@ int did_set_spelltab;
char *e_format = N_("E759: Format error in spell file");
// Remember what "z?" replaced.
-char_u *repl_from = NULL;
-char_u *repl_to = NULL;
+char *repl_from = NULL;
+char *repl_to = NULL;
/// Main spell-checking function.
/// "ptr" points to a character that could be the start of a word.
@@ -209,11 +219,9 @@ 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 use_camel_case = (wp->w_s->b_p_spo_flags & SPO_CAMEL) != 0;
bool camel_case = false;
// A word never starts at a space or a control character. Return quickly
@@ -236,7 +244,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 +258,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 +266,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 +275,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 +316,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
@@ -361,7 +369,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
int r = vim_regexec(&regmatch, (char *)ptr, 0);
wp->w_s->b_cap_prog = regmatch.regprog;
if (r) {
- *capcol = (int)(regmatch.endp[0] - ptr);
+ *capcol = (int)(regmatch.endp[0] - (char *)ptr);
}
}
@@ -468,7 +476,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 +487,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.
@@ -565,7 +572,7 @@ static void find_word(matchinf_T *mip, int mode)
arridx = endidx[endidxcnt];
wlen = endlen[endidxcnt];
- if (utf_head_off(ptr, ptr + wlen) > 0) {
+ if (utf_head_off((char *)ptr, (char *)ptr + wlen) > 0) {
continue; // not at first byte of character
}
if (spell_iswordp(ptr + wlen, mip->mi_win)) {
@@ -597,7 +604,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 +623,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 +758,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 +797,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 +838,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 +910,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 +962,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 +1016,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 +1058,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 +1085,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 +1125,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 +1157,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 +1170,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;
}
@@ -1214,6 +1199,24 @@ bool no_spell_checking(win_T *wp)
return false;
}
+static void decor_spell_nav_start(win_T *wp)
+{
+ decor_state = (DecorState){ 0 };
+ decor_redraw_reset(wp->w_buffer, &decor_state);
+}
+
+static bool decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_lnum, int col,
+ char **decor_error)
+{
+ if (*decor_lnum != lnum) {
+ decor_providers_invoke_spell(wp, lnum - 1, col, lnum - 1, -1, decor_error);
+ decor_redraw_line(wp->w_buffer, lnum - 1, &decor_state);
+ *decor_lnum = lnum;
+ }
+ decor_redraw_col(wp->w_buffer, col, col, false, &decor_state);
+ return decor_state.spell;
+}
+
/// Moves to the next spell error.
/// "curline" is false for "[s", "]s", "[S" and "]S".
/// "curline" is true to find word under/after cursor in the same line.
@@ -1227,21 +1230,16 @@ 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;
+ colnr_T col;
char_u *buf = NULL;
size_t buflen = 0;
int skip = 0;
- int capcol = -1;
+ colnr_T capcol = -1;
bool found_one = false;
bool wrapped = false;
@@ -1249,6 +1247,8 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
return 0;
}
+ size_t ret = 0;
+
// Start looking for bad word at the start of the line, because we can't
// start halfway through a word, we don't know where it starts or ends.
//
@@ -1258,11 +1258,24 @@ 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);
+ char *decor_error = NULL;
+ // Ephemeral extmarks are currently stored in the global decor_state.
+ // When looking for spell errors, we need to:
+ // - temporarily reset decor_state
+ // - run the _on_spell_nav decor callback for each line we look at
+ // - detect if any spell marks are present
+ // - restore decor_state to the value saved here.
+ // TODO(lewis6991): un-globalize decor_state and allow ephemeral marks to be stored into a
+ // temporary DecorState.
+ DecorState saved_decor_start = decor_state;
+ linenr_T decor_lnum = -1;
+ decor_spell_nav_start(wp);
+
while (!got_int) {
- line = ml_get_buf(wp->w_buffer, lnum, false);
+ char_u *line = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
len = STRLEN(line);
if (buflen < len + MAXWLEN + 2) {
@@ -1279,17 +1292,17 @@ 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 = (colnr_T)getwhitecols((char *)line);
} else if (curline && wp == curwin) {
// For spellbadword(): check if first word needs a capital.
- col = (int)getwhitecols(line);
+ col = (colnr_T)getwhitecols((char *)line);
if (check_need_cap(lnum, col)) {
capcol = col;
}
// Need to get the line again, may have looked at the previous
// one.
- line = ml_get_buf(wp->w_buffer, lnum, false);
+ line = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
}
// Copy the line into "buf" and append the start of the next line if
@@ -1299,11 +1312,11 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
STRCPY(buf, line);
if (lnum < wp->w_buffer->b_ml.ml_line_count) {
spell_cat_line(buf + STRLEN(buf),
- ml_get_buf(wp->w_buffer, lnum + 1, false),
+ (char_u *)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,30 +1342,37 @@ 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)) {
- if (has_syntax) {
- col = (int)(p - buf);
- (void)syn_get_id(wp, lnum, (colnr_T)col,
- FALSE, &can_spell, FALSE);
- if (!can_spell) {
- attr = HLF_COUNT;
- }
- } else {
- can_spell = true;
+ col = (colnr_T)(p - buf);
+
+ bool can_spell = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) == 0;
+
+ if (!can_spell) {
+ can_spell = decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error);
+ }
+
+ if (!can_spell && has_syntax) {
+ (void)syn_get_id(wp, lnum, col, false, &can_spell, false);
+ }
+
+ if (!can_spell) {
+ attr = HLF_COUNT;
}
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 = col,
+ .coladd = 0
+ };
if (dir == FORWARD) {
// No need to search further.
wp->w_cursor = found_pos;
- xfree(buf);
if (attrp != NULL) {
*attrp = attr;
}
- return len;
+ ret = len;
+ goto theend;
} else if (curline) {
// Insert mode completion: put cursor after
// the bad word.
@@ -1376,8 +1396,8 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
if (dir == BACKWARD && found_pos.lnum != 0) {
// Use the last match in the line (before the cursor).
wp->w_cursor = found_pos;
- xfree(buf);
- return found_len;
+ ret = found_len;
+ goto theend;
}
if (curline) {
@@ -1447,8 +1467,12 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
line_breakcheck();
}
+theend:
+ decor_state_free(&decor_state);
+ xfree(decor_error);
+ decor_state = saved_decor_start;
xfree(buf);
- return 0;
+ return ret;
}
// For spell checking: concatenate the start of the following line "line" into
@@ -1457,10 +1481,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 +1489,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 +1504,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 +1513,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());
@@ -1539,8 +1559,8 @@ static void spell_load_lang(char_u *lang)
// use "latin1" for "latin9". And limit to 60 characters (just in case).
char_u *spell_enc(void)
{
- if (STRLEN(p_enc) < 60 && STRCMP(p_enc, "iso-8859-15") != 0) {
- return p_enc;
+ if (STRLEN(p_enc) < 60 && strcmp(p_enc, "iso-8859-15") != 0) {
+ return (char_u *)p_enc;
}
return (char_u *)"latin1";
}
@@ -1553,15 +1573,15 @@ static void int_wordlist_spl(char_u *fname)
int_wordlist, spell_enc());
}
-// Allocate a new slang_T for language "lang". "lang" can be NULL.
-// Caller must fill "sl_next".
-slang_T *slang_alloc(char_u *lang)
+/// Allocate a new slang_T for language "lang". "lang" can be NULL.
+/// Caller must fill "sl_next".
+slang_T *slang_alloc(char *lang)
FUNC_ATTR_NONNULL_RET
{
slang_T *lp = xcalloc(1, sizeof(slang_T));
if (lang != NULL) {
- lp->sl_name = vim_strsave(lang);
+ lp->sl_name = xstrdup(lang);
}
ga_init(&lp->sl_rep, sizeof(fromto_T), 10);
ga_init(&lp->sl_repsal, sizeof(fromto_T), 10);
@@ -1624,7 +1644,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 +1693,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(fname, (char *)slp->sl_lang, NULL, false);
if (slang != NULL) {
// When a previously loaded file has NOBREAK also use it for the
// ".add" files.
@@ -1698,9 +1716,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 +1728,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 +1750,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 +1762,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 +1797,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 +1812,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 +1824,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,31 +1837,31 @@ 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;
char *splp;
- char_u *region;
- char_u region_cp[3];
+ char *region;
+ char region_cp[3];
bool filename;
int region_mask;
slang_T *slang;
int c;
- char_u lang[MAXWLEN + 1];
- char_u spf_name[MAXPATHL];
+ char lang[MAXWLEN + 1];
+ char spf_name[MAXPATHL];
int len;
- char_u *p;
+ char *p;
int round;
char *spf;
- char_u *use_region = NULL;
+ char *use_region = NULL;
bool dont_use_region = false;
bool nobreak = false;
langp_T *lp, *lp2;
static bool recursive = false;
char *ret_msg = NULL;
- char_u *spl_copy;
+ char *spl_copy;
bufref_T bufref;
set_bufref(&bufref, wp->w_buffer);
@@ -1870,22 +1879,22 @@ 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 = xstrdup(wp->w_s->b_p_spl);
wp->w_s->b_cjk = 0;
// Loop over comma separated language names.
- for (splp = (char *)spl_copy; *splp != NUL;) {
+ for (splp = spl_copy; *splp != NUL;) {
// Get one language name.
copy_option_part(&splp, (char *)lang, MAXWLEN, ",");
region = NULL;
len = (int)STRLEN(lang);
- if (!valid_spelllang(lang)) {
+ if (!valid_spelllang((char *)lang)) {
continue;
}
- if (STRCMP(lang, "cjk") == 0) {
+ if (strcmp(lang, "cjk") == 0) {
wp->w_s->b_cjk = 1;
continue;
}
@@ -1893,11 +1902,11 @@ char *did_set_spelllang(win_T *wp)
// If the name ends in ".spl" use it as the name of the spell file.
// If there is a region name let "region" point to it and remove it
// from the name.
- if (len > 4 && FNAMECMP(lang + len - 4, ".spl") == 0) {
+ if (len > 4 && path_fnamecmp(lang + len - 4, ".spl") == 0) {
filename = true;
// Locate a region and remove it from the file name.
- p = (char_u *)vim_strchr(path_tail((char *)lang), '_');
+ p = vim_strchr(path_tail((char *)lang), '_');
if (p != NULL && ASCII_ISALPHA(p[1]) && ASCII_ISALPHA(p[2])
&& !ASCII_ISALPHA(p[3])) {
STRLCPY(region_cp, p + 1, 3);
@@ -1909,7 +1918,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;
}
@@ -1934,7 +1943,7 @@ char *did_set_spelllang(win_T *wp)
if (region != NULL) {
// If the region differs from what was used before then don't
// use it for 'spellfile'.
- if (use_region != NULL && STRCMP(region, use_region) != 0) {
+ if (use_region != NULL && strcmp(region, use_region) != 0) {
dont_use_region = true;
}
use_region = region;
@@ -1943,9 +1952,9 @@ char *did_set_spelllang(win_T *wp)
// If not found try loading the language now.
if (slang == NULL) {
if (filename) {
- (void)spell_load_file(lang, lang, NULL, false);
+ (void)spell_load_file((char *)lang, (char *)lang, NULL, false);
} else {
- spell_load_lang(lang);
+ spell_load_lang((char_u *)lang);
// SpellFileMissing autocommands may do anything, including
// destroying the buffer we are using...
if (!bufref_valid(&bufref)) {
@@ -1958,12 +1967,12 @@ 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) {
// find region in sl_regions
- c = find_region(slang->sl_regions, region);
+ c = find_region(slang->sl_regions, (char_u *)region);
if (c == REGION_ALL) {
if (slang->sl_add) {
if (*slang->sl_regions != NUL) {
@@ -1999,24 +2008,24 @@ 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.
if (int_wordlist == NULL) {
continue;
}
- int_wordlist_spl(spf_name);
+ int_wordlist_spl((char_u *)spf_name);
} else {
// One entry in 'spellfile'.
copy_option_part(&spf, (char *)spf_name, MAXPATHL - 5, ",");
STRCAT(spf_name, ".spl");
// If it was already found above then skip it.
- for (c = 0; c < ga.ga_len; ++c) {
+ for (c = 0; c < ga.ga_len; c++) {
p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname;
if (p != NULL
- && path_full_compare((char *)spf_name, (char *)p, false, true) == kEqualFiles) {
+ && path_full_compare((char *)spf_name, p, false, true) == kEqualFiles) {
break;
}
}
@@ -2027,7 +2036,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;
}
@@ -2040,12 +2049,12 @@ char *did_set_spelllang(win_T *wp)
STRCPY(lang, "internal wordlist");
} else {
STRLCPY(lang, path_tail((char *)spf_name), MAXWLEN + 1);
- p = (char_u *)vim_strchr((char *)lang, '.');
+ p = vim_strchr((char *)lang, '.');
if (p != NULL) {
*p = NUL; // truncate at ".encoding.add"
}
}
- slang = spell_load_file(spf_name, lang, NULL, true);
+ slang = spell_load_file((char *)spf_name, (char *)lang, NULL, true);
// If one of the languages has NOBREAK we assume the addition
// files also have this.
@@ -2057,7 +2066,7 @@ char *did_set_spelllang(win_T *wp)
region_mask = REGION_ALL;
if (use_region != NULL && !dont_use_region) {
// find region in sl_regions
- c = find_region(slang->sl_regions, use_region);
+ c = find_region(slang->sl_regions, (char_u *)use_region);
if (c != REGION_ALL) {
region_mask = 1 << c;
} else if (*slang->sl_regions != NUL) {
@@ -2085,7 +2094,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 +2103,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 +2120,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 +2131,7 @@ char *did_set_spelllang(win_T *wp)
}
}
}
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
theend:
xfree(spl_copy);
@@ -2137,8 +2146,8 @@ static void clear_midword(win_T *wp)
XFREE_CLEAR(wp->w_s->b_spell_ismw_mb);
}
-// Use the "sl_midword" field of language "lp" for buffer "buf".
-// They add up to any currently used midword characters.
+/// Use the "sl_midword" field of language "lp" for buffer "buf".
+/// They add up to any currently used midword characters.
static void use_midword(slang_T *lp, win_T *wp)
FUNC_ATTR_NONNULL_ALL
{
@@ -2146,18 +2155,18 @@ static void use_midword(slang_T *lp, win_T *wp)
return;
}
- for (char_u *p = lp->sl_midword; *p != NUL;) {
- const int c = utf_ptr2char((char *)p);
- const int l = utfc_ptr2len((char *)p);
+ for (char *p = (char *)lp->sl_midword; *p != NUL;) {
+ const int c = utf_ptr2char(p);
+ const int l = utfc_ptr2len(p);
if (c < 256 && l <= 2) {
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 = xstrnsave(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 *bp = xstrnsave(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;
STRLCPY(bp + n, p, l + 1);
@@ -2198,9 +2207,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 +2215,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 +2250,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 +2262,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 +2325,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 +2333,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 +2364,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 +2389,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 +2397,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 +2447,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,30 +2507,26 @@ 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 = (char_u *)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) {
need_cap = true;
} else {
- line = ml_get(lnum - 1);
+ line = (char_u *)ml_get(lnum - 1);
if (*skipwhite((char *)line) == NUL) {
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,16 +2537,18 @@ 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)) {
break;
}
if (vim_regexec(&regmatch, (char *)p, 0)
- && regmatch.endp[0] == line + endcol) {
+ && (char_u *)regmatch.endp[0] == line + endcol) {
need_cap = true;
break;
}
@@ -2568,10 +2565,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 +2572,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 +2590,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 = (char_u *)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 +2741,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 +2813,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 +2851,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 +2866,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 +2878,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 +2939,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 +2951,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 +3093,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 +3134,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 +3159,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:
@@ -3181,24 +3171,23 @@ void ex_spelldump(exarg_T *eap)
/// @param ic ignore case
/// @param dir direction for adding matches
/// @param dumpflags_arg DUMPFLAG_*
-void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)
+void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
{
langp_T *lp;
slang_T *slang;
idx_T arridx[MAXWLEN];
int curi[MAXWLEN];
- char_u word[MAXWLEN];
+ char word[MAXWLEN];
int c;
- char_u *byts;
+ char *byts;
idx_T *idxs;
linenr_T lnum = 0;
- int round;
int depth;
int n;
int flags;
- char_u *region_names = NULL; // region names being used
+ char *region_names = NULL; // region names being used
bool do_region = true; // dump region names and numbers
- char_u *p;
+ char *p;
int dumpflags = dumpflags_arg;
int patlen;
@@ -3208,11 +3197,11 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)
if (ic) {
dumpflags |= DUMPFLAG_ICASE;
} else {
- n = captype(pat, NULL);
+ n = captype((char_u *)pat, NULL);
if (n == WF_ONECAP) {
dumpflags |= DUMPFLAG_ONECAP;
} else if (n == WF_ALLCAP
- && (int)STRLEN(pat) > utfc_ptr2len((char *)pat)) {
+ && (int)STRLEN(pat) > utfc_ptr2len(pat)) {
dumpflags |= DUMPFLAG_ALLCAP;
}
}
@@ -3220,13 +3209,13 @@ 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;
+ p = (char *)lp->lp_slang->sl_regions;
if (p[0] != 0) {
if (region_names == NULL) { // first language with regions
region_names = p;
- } else if (STRCMP(region_names, p) != 0) {
+ } else if (strcmp(region_names, p) != 0) {
do_region = false; // region names are different
break;
}
@@ -3243,7 +3232,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,14 +3254,14 @@ 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;
+ byts = (char *)slang->sl_fbyts;
idxs = slang->sl_fidxs;
} else {
dumpflags |= DUMPFLAG_KEEPCASE;
- byts = slang->sl_kbyts;
+ byts = (char *)slang->sl_kbyts;
idxs = slang->sl_kidxs;
}
if (byts == NULL) {
@@ -3291,8 +3280,8 @@ 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];
- c = byts[n];
+ curi[depth]++;
+ c = (uint8_t)byts[n];
if (c == 0 || depth >= MAXWLEN - 1) {
// End of word or reached maximum length, deal with the
// word.
@@ -3315,7 +3304,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)
// when it's the first one.
c = (int)((unsigned)flags >> 24);
if (c == 0 || curi[depth] == 2) {
- dump_word(slang, word, pat, dir,
+ dump_word(slang, (char_u *)word, (char_u *)pat, dir,
dumpflags, flags, lnum);
if (pat == NULL) {
lnum++;
@@ -3324,13 +3313,13 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)
// Apply the prefix, if there is one.
if (c != 0) {
- lnum = dump_prefixes(slang, word, pat, dir,
+ lnum = dump_prefixes(slang, (char_u *)word, (char_u *)pat, dir,
dumpflags, flags, lnum);
}
}
} else {
// Normal char, go one level deeper.
- word[depth++] = (char_u)c;
+ word[depth++] = (char)c;
arridx[depth] = idxs[n];
curi[depth] = 1;
@@ -3342,7 +3331,7 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)
// ignore case...
assert(depth >= 0);
if (depth <= patlen
- && mb_strnicmp(word, pat, (size_t)depth) != 0) {
+ && mb_strnicmp((char *)word, pat, (size_t)depth) != 0) {
depth--;
}
}
@@ -3359,10 +3348,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 +3371,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 +3387,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,
@@ -3420,13 +3407,13 @@ static void dump_word(slang_T *slang, char_u *word, char_u *pat, Direction *dir,
if (!HASHITEM_EMPTY(hi)) {
vim_snprintf((char *)IObuff, IOSIZE, "%s\t%d",
tw, HI2WC(hi)->wc_count);
- p = IObuff;
+ p = (char_u *)IObuff;
}
}
ml_append(lnum, (char *)p, (colnr_T)0, false);
} else if (((dumpflags & DUMPFLAG_ICASE)
- ? mb_strnicmp(p, pat, STRLEN(pat)) == 0
+ ? mb_strnicmp((char *)p, (char *)pat, STRLEN(pat)) == 0
: STRNCMP(p, pat, STRLEN(pat)) == 0)
&& ins_compl_add_infercase(p, (int)STRLEN(p),
p_ic, NULL, *dir, false) == OK) {
@@ -3451,34 +3438,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 +3466,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 +3482,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 +3497,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 +3535,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 = (char_u *)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 +3550,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 +3587,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;
}
@@ -3634,7 +3613,7 @@ char *did_set_spell_option(bool is_spellfile)
if (is_spellfile) {
int l = (int)STRLEN(curwin->w_s->b_p_spf);
if (l > 0
- && (l < 4 || STRCMP(curwin->w_s->b_p_spf + l - 4, ".add") != 0)) {
+ && (l < 4 || strcmp(curwin->w_s->b_p_spf + l - 4, ".add") != 0)) {
errmsg = e_invarg;
}
}
@@ -3657,14 +3636,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..2c4aebe420 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 *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
@@ -252,7 +252,7 @@ typedef struct wordcount_S {
#define MAXWORDCOUNT 0xffff
// Remember what "z?" replaced.
-extern char_u *repl_from;
-extern char_u *repl_to;
+extern char *repl_from;
+extern char *repl_to;
#endif // NVIM_SPELL_DEFS_H
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index be1373f617..7da5a7ca4f 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -355,12 +355,12 @@ struct affentry_S {
// Affix header from ".aff" file. Used for af_pref and af_suff.
typedef struct affheader_S {
- char_u ah_key[AH_KEY_LEN]; // key for hashtab == name of affix
+ char ah_key[AH_KEY_LEN]; // key for hashtab == name of affix
unsigned ah_flag; // affix name as number, uses "af_flagtype"
int ah_newID; // prefix ID after renumbering; 0 if not used
int ah_combine; // suffix may combine with prefix
int ah_follows; // another affix block should be following
- affentry_T *ah_first; // first affix entry
+ affentry_T *ah_first; // first affix entry
} affheader_T;
#define HI2AH(hi) ((affheader_T *)(hi)->hi_key)
@@ -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
@@ -572,10 +572,10 @@ static inline int spell_check_magic_string(FILE *const fd)
/// @param silent no error if file doesn't exist
///
/// @return the slang_T the spell file was loaded into. NULL for error.
-slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool silent)
+slang_T *spell_load_file(char *fname, char *lang, slang_T *old_lp, bool silent)
{
FILE *fd;
- char_u *p;
+ char *p;
int n;
int len;
slang_T *lp = NULL;
@@ -583,7 +583,7 @@ slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool sile
int res;
bool did_estack_push = false;
- fd = os_fopen((char *)fname, "r");
+ fd = os_fopen(fname, "r");
if (fd == NULL) {
if (!silent) {
semsg(_(e_notopen), fname);
@@ -604,16 +604,16 @@ 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 = xstrdup(fname);
// Check for .add.spl.
- lp->sl_add = strstr(path_tail((char *)fname), SPL_FNAME_ADD) != NULL;
+ lp->sl_add = strstr(path_tail(fname), SPL_FNAME_ADD) != NULL;
} else {
lp = old_lp;
}
// Set sourcing_name, so that error messages mention the file name.
- estack_push(ETYPE_SPELL, (char *)fname, 0);
+ estack_push(ETYPE_SPELL, fname, 0);
did_estack_push = true;
// <HEADER>: <fileID>
@@ -697,11 +697,11 @@ slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool sile
break;
case SN_MAP:
- p = READ_STRING(fd, len); // <mapstr>
+ p = (char *)READ_STRING(fd, len); // <mapstr>
if (p == NULL) {
goto endFAIL;
}
- set_map_str(lp, p);
+ set_map_str(lp, (char_u *)p);
xfree(p);
break;
@@ -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, '.');
- if (dotp == NULL || FNAMECMP(dotp, ".spl") != 0) {
+ dotp = strrchr(slang->sl_fname, '.');
+ if (dotp == NULL || path_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) {
+ if (spell_load_file((char *)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) {
@@ -1994,7 +1994,7 @@ static void spell_print_tree(wordnode_T *root)
}
}
-#endif // SPELL_PRINTTREE
+#endif // SPELL_PRINTTREE
// Reads the affix file "fname".
// Returns an afffile_T, NULL for complete failure.
@@ -2005,17 +2005,17 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
char_u *line;
char_u *pc = NULL;
#define MAXITEMCNT 30
- char_u *(items[MAXITEMCNT]);
+ char *(items[MAXITEMCNT]);
int itemcnt;
- char_u *p;
+ char *p;
int lnum = 0;
affheader_T *cur_aff = NULL;
bool did_postpone_prefix = false;
int aff_todo = 0;
hashtab_T *tp;
- char_u *low = NULL;
- char_u *fol = NULL;
- char_u *upp = NULL;
+ char *low = NULL;
+ char *fol = NULL;
+ char *upp = NULL;
int do_rep;
int do_repsal;
int do_sal;
@@ -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);
@@ -2090,8 +2090,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Split the line up in white separated items. Put a NUL after each
// item.
itemcnt = 0;
- for (p = line;;) {
- while (*p != NUL && *p <= ' ') { // skip white space and CR/NL
+ for (p = (char *)line;;) {
+ while (*p != NUL && (uint8_t)(*p) <= ' ') { // skip white space and CR/NL
p++;
}
if (*p == NUL) {
@@ -2103,11 +2103,11 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
items[itemcnt++] = p;
// A few items have arbitrary text argument, don't split them.
if (itemcnt == 2 && spell_info_item(items[0])) {
- while (*p >= ' ' || *p == TAB) { // skip until CR/NL
+ while ((uint8_t)(*p) >= ' ' || *p == TAB) { // skip until CR/NL
p++;
}
} else {
- while (*p > ' ') { // skip until white space or CR/NL
+ while ((uint8_t)(*p) > ' ') { // skip until white space or CR/NL
p++;
}
}
@@ -2121,21 +2121,20 @@ 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);
}
spin->si_conv.vc_fail = true;
} else if (is_aff_rule(items, itemcnt, "FLAG", 2)
&& aff->af_flagtype == AFT_CHAR) {
- if (STRCMP(items[1], "long") == 0) {
+ if (strcmp(items[1], "long") == 0) {
aff->af_flagtype = AFT_LONG;
- } else if (STRCMP(items[1], "num") == 0) {
+ } else if (strcmp(items[1], "num") == 0) {
aff->af_flagtype = AFT_NUM;
- } else if (STRCMP(items[1], "caplong") == 0) {
+ } else if (strcmp(items[1], "caplong") == 0) {
aff->af_flagtype = AFT_CAPLONG;
} else {
smsg(_("Invalid value for FLAG in %s line %d: %s"),
@@ -2167,10 +2166,9 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
STRCAT(p, items[0]);
STRCAT(p, " ");
STRCAT(p, items[1]);
- spin->si_info = p;
- } else if (is_aff_rule(items, itemcnt, "MIDWORD", 2)
- && midword == NULL) {
- midword = getroom_save(spin, items[1]);
+ spin->si_info = (char_u *)p;
+ } else if (is_aff_rule(items, itemcnt, "MIDWORD", 2) && midword == NULL) {
+ midword = (char_u *)getroom_save(spin, (char_u *)items[1]);
} else if (is_aff_rule(items, itemcnt, "TRY", 2)) {
// ignored, we look in the tree for what chars may appear
}
@@ -2178,44 +2176,44 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
else if ((is_aff_rule(items, itemcnt, "RAR", 2)
|| is_aff_rule(items, itemcnt, "RARE", 2))
&& aff->af_rare == 0) {
- aff->af_rare = affitem2flag(aff->af_flagtype, items[1],
+ aff->af_rare = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
}
// TODO: remove "KEP" later
else if ((is_aff_rule(items, itemcnt, "KEP", 2)
|| is_aff_rule(items, itemcnt, "KEEPCASE", 2))
&& aff->af_keepcase == 0) {
- aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1],
+ aff->af_keepcase = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
} else if ((is_aff_rule(items, itemcnt, "BAD", 2)
|| is_aff_rule(items, itemcnt, "FORBIDDENWORD", 2))
&& aff->af_bad == 0) {
- aff->af_bad = affitem2flag(aff->af_flagtype, items[1],
+ aff->af_bad = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
} else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2)
&& aff->af_needaffix == 0) {
- aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1],
+ aff->af_needaffix = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
} else if (is_aff_rule(items, itemcnt, "CIRCUMFIX", 2)
&& aff->af_circumfix == 0) {
- aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1],
+ aff->af_circumfix = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
} else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2)
&& aff->af_nosuggest == 0) {
- aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1],
+ aff->af_nosuggest = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
} else if ((is_aff_rule(items, itemcnt, "NEEDCOMPOUND", 2)
|| is_aff_rule(items, itemcnt, "ONLYINCOMPOUND", 2))
&& aff->af_needcomp == 0) {
- aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1],
+ aff->af_needcomp = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
} else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2)
&& aff->af_comproot == 0) {
- aff->af_comproot = affitem2flag(aff->af_flagtype, items[1],
+ aff->af_comproot = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
} else if (is_aff_rule(items, itemcnt, "COMPOUNDFORBIDFLAG", 2)
&& aff->af_compforbid == 0) {
- aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1],
+ aff->af_compforbid = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
if (aff->af_pref.ht_used > 0) {
smsg(_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"),
@@ -2223,7 +2221,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
} else if (is_aff_rule(items, itemcnt, "COMPOUNDPERMITFLAG", 2)
&& aff->af_comppermit == 0) {
- aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1],
+ aff->af_comppermit = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
if (aff->af_pref.ht_used > 0) {
smsg(_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"),
@@ -2236,7 +2234,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
p = getroom(spin, STRLEN(items[1]) + 2, false);
STRCPY(p, items[1]);
STRCAT(p, "+");
- compflags = p;
+ compflags = (char_u *)p;
} else if (is_aff_rule(items, itemcnt, "COMPOUNDRULES", 2)) {
// We don't use the count, but do check that it's a number and
// not COMPOUNDRULE mistyped.
@@ -2259,7 +2257,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
STRCAT(p, "/");
}
STRCAT(p, items[1]);
- compflags = p;
+ compflags = (char_u *)p;
}
} else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2)
&& compmax == 0) {
@@ -2301,19 +2299,19 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Only add the couple if it isn't already there.
for (i = 0; i < gap->ga_len - 1; i += 2) {
- if (STRCMP(((char **)(gap->ga_data))[i], items[1]) == 0
- && STRCMP(((char **)(gap->ga_data))[i + 1], items[2]) == 0) {
+ if (strcmp(((char **)(gap->ga_data))[i], items[1]) == 0
+ && strcmp(((char **)(gap->ga_data))[i + 1], items[2]) == 0) {
break;
}
}
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, (char_u *)items[1]);
+ ((char **)(gap->ga_data))[gap->ga_len++] = getroom_save(spin, (char_u *)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, (char_u *)items[1]);
} else if (is_aff_rule(items, itemcnt, "NOBREAK", 1)) {
spin->si_nobreak = true;
} else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1)) {
@@ -2326,8 +2324,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
aff->af_pfxpostpone = true;
} else if (is_aff_rule(items, itemcnt, "IGNOREEXTRA", 1)) {
aff->af_ignoreextra = true;
- } else if ((STRCMP(items[0], "PFX") == 0
- || STRCMP(items[0], "SFX") == 0)
+ } else if ((strcmp(items[0], "PFX") == 0
+ || strcmp(items[0], "SFX") == 0)
&& aff_todo == 0
&& itemcnt >= 4) {
int lasti = 4;
@@ -2358,7 +2356,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
} else {
// New affix letter.
cur_aff = getroom(spin, sizeof(*cur_aff), true);
- cur_aff->ah_flag = affitem2flag(aff->af_flagtype, items[1],
+ cur_aff->ah_flag = affitem2flag(aff->af_flagtype, (char_u *)items[1],
fname, lnum);
if (cur_aff->ah_flag == 0 || STRLEN(items[1]) >= AH_KEY_LEN) {
break;
@@ -2377,14 +2375,14 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
fname, lnum, items[1]);
}
STRCPY(cur_aff->ah_key, items[1]);
- hash_add(tp, cur_aff->ah_key);
+ hash_add(tp, (char_u *)cur_aff->ah_key);
cur_aff->ah_combine = (*items[2] == 'Y');
}
// Check for the "S" flag, which apparently means that another
// block with the same affix name is following.
- if (itemcnt > lasti && STRCMP(items[lasti], "S") == 0) {
+ if (itemcnt > lasti && strcmp(items[lasti], "S") == 0) {
lasti++;
cur_aff->ah_follows = true;
} else {
@@ -2400,7 +2398,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
smsg(_(e_afftrailing), fname, lnum, items[lasti]);
}
- if (STRCMP(items[2], "Y") != 0 && STRCMP(items[2], "N") != 0) {
+ if (strcmp(items[2], "Y") != 0 && strcmp(items[2], "N") != 0) {
smsg(_("Expected Y or N in %s line %d: %s"),
fname, lnum, items[2]);
}
@@ -2423,10 +2421,10 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
aff_todo = atoi((char *)items[3]);
- } else if ((STRCMP(items[0], "PFX") == 0
- || STRCMP(items[0], "SFX") == 0)
+ } else if ((strcmp(items[0], "PFX") == 0
+ || strcmp(items[0], "SFX") == 0)
&& aff_todo > 0
- && STRCMP(cur_aff->ah_key, items[1]) == 0
+ && strcmp(cur_aff->ah_key, items[1]) == 0
&& itemcnt >= 5) {
affentry_T *aff_entry;
bool upper = false;
@@ -2436,7 +2434,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// mean mistakes go unnoticed. Require a comment-starter.
// Hunspell uses a "-" item.
if (itemcnt > lasti && *items[lasti] != '#'
- && (STRCMP(items[lasti], "-") != 0
+ && (strcmp(items[lasti], "-") != 0
|| itemcnt != lasti + 1)) {
smsg(_(e_afftrailing), fname, lnum, items[lasti]);
}
@@ -2445,11 +2443,11 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
aff_todo--;
aff_entry = getroom(spin, sizeof(*aff_entry), true);
- if (STRCMP(items[2], "0") != 0) {
- aff_entry->ae_chop = getroom_save(spin, items[2]);
+ if (strcmp(items[2], "0") != 0) {
+ aff_entry->ae_chop = (char_u *)getroom_save(spin, (char_u *)items[2]);
}
- if (STRCMP(items[3], "0") != 0) {
- aff_entry->ae_add = getroom_save(spin, items[3]);
+ if (strcmp(items[3], "0") != 0) {
+ aff_entry->ae_add = (char_u *)getroom_save(spin, (char_u *)items[3]);
// Recognize flags on the affix: abcd/XYZ
aff_entry->ae_flags = (char_u *)vim_strchr((char *)aff_entry->ae_add, '/');
@@ -2466,10 +2464,10 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
aff_entry->ae_next = cur_aff->ah_first;
cur_aff->ah_first = aff_entry;
- if (STRCMP(items[4], ".") != 0) {
+ 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, (char_u *)items[4]);
if (*items[0] == 'P') {
sprintf((char *)buf, "^%s", items[4]);
} else {
@@ -2504,10 +2502,10 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if (c_up != c
&& (aff_entry->ae_cond == NULL
|| utf_ptr2char((char *)aff_entry->ae_cond) == c)) {
- p = aff_entry->ae_add
+ p = (char *)aff_entry->ae_add
+ STRLEN(aff_entry->ae_add);
MB_PTR_BACK(aff_entry->ae_add, p);
- if (utf_ptr2char((char *)p) == c_up) {
+ if (utf_ptr2char(p) == c_up) {
upper = true;
aff_entry->ae_chop = NULL;
*p = NUL;
@@ -2517,8 +2515,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// upper-case letter.
if (aff_entry->ae_cond != NULL) {
char_u buf[MAXLINELEN];
- onecap_copy(items[4], buf, true);
- aff_entry->ae_cond = getroom_save(spin, buf);
+ onecap_copy((char_u *)items[4], buf, true);
+ aff_entry->ae_cond = (char_u *)getroom_save(spin, buf);
if (aff_entry->ae_cond != NULL) {
sprintf((char *)buf, "^%s",
aff_entry->ae_cond);
@@ -2536,10 +2534,9 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
int n;
// Find a previously used condition.
- for (idx = spin->si_prefcond.ga_len - 1; idx >= 0;
- --idx) {
- p = ((char_u **)spin->si_prefcond.ga_data)[idx];
- if (str_equal(p, aff_entry->ae_cond)) {
+ for (idx = spin->si_prefcond.ga_len - 1; idx >= 0; idx--) {
+ p = ((char **)spin->si_prefcond.ga_data)[idx];
+ if (str_equal(p, (char *)aff_entry->ae_cond)) {
break;
}
}
@@ -2548,14 +2545,14 @@ 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.
if (aff_entry->ae_add == NULL) {
- p = (char_u *)"";
+ p = "";
} else {
- p = aff_entry->ae_add;
+ p = (char *)aff_entry->ae_add;
}
// PFX_FLAGS is a negative number, so that
@@ -2573,24 +2570,24 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if (aff_entry->ae_compforbid) {
n |= WFP_COMPFORBID;
}
- tree_add_word(spin, p, spin->si_prefroot, n,
+ tree_add_word(spin, (char_u *)p, spin->si_prefroot, n,
idx, cur_aff->ah_newID);
did_postpone_prefix = true;
}
// Didn't actually use ah_newID, backup si_newprefID.
if (aff_todo == 0 && !did_postpone_prefix) {
- --spin->si_newprefID;
+ spin->si_newprefID--;
cur_aff->ah_newID = 0;
}
}
}
} else if (is_aff_rule(items, itemcnt, "FOL", 2) && fol == NULL) {
- fol = vim_strsave(items[1]);
+ fol = xstrdup(items[1]);
} else if (is_aff_rule(items, itemcnt, "LOW", 2) && low == NULL) {
- low = vim_strsave(items[1]);
+ low = xstrdup(items[1]);
} else if (is_aff_rule(items, itemcnt, "UPP", 2) && upp == NULL) {
- upp = vim_strsave(items[1]);
+ upp = xstrdup(items[1]);
} else if (is_aff_rule(items, itemcnt, "REP", 2)
|| is_aff_rule(items, itemcnt, "REPSAL", 2)) {
// Ignore REP/REPSAL count
@@ -2598,8 +2595,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
smsg(_("Expected REP(SAL) count in %s line %d"),
fname, lnum);
}
- } else if ((STRCMP(items[0], "REP") == 0
- || STRCMP(items[0], "REPSAL") == 0)
+ } else if ((strcmp(items[0], "REP") == 0
+ || strcmp(items[0], "REPSAL") == 0)
&& itemcnt >= 3) {
// REP/REPSAL item
// Myspell ignores extra arguments, we require it starts with
@@ -2621,8 +2618,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
}
add_fromto(spin, items[0][3] == 'S'
- ? &spin->si_repsal
- : &spin->si_rep, items[1], items[2]);
+ ? &spin->si_repsal
+ : &spin->si_rep, (char_u *)items[1], (char_u *)items[2]);
}
} else if (is_aff_rule(items, itemcnt, "MAP", 2)) {
// MAP item or count
@@ -2642,7 +2639,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if ((!GA_EMPTY(&spin->si_map)
&& vim_strchr(spin->si_map.ga_data, c)
!= NULL)
- || vim_strchr((char *)p, c) != NULL) {
+ || vim_strchr(p, c) != NULL) {
smsg(_("Duplicate character in MAP in %s line %d"),
fname, lnum);
}
@@ -2659,32 +2656,32 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if (do_sal) {
// SAL item (sounds-a-like)
// Either one of the known keys or a from-to pair.
- if (STRCMP(items[1], "followup") == 0) {
+ if (strcmp(items[1], "followup") == 0) {
spin->si_followup = sal_to_bool(items[2]);
- } else if (STRCMP(items[1], "collapse_result") == 0) {
+ } else if (strcmp(items[1], "collapse_result") == 0) {
spin->si_collapse = sal_to_bool(items[2]);
- } else if (STRCMP(items[1], "remove_accents") == 0) {
+ } else if (strcmp(items[1], "remove_accents") == 0) {
spin->si_rem_accents = sal_to_bool(items[2]);
} else {
// when "to" is "_" it means empty
- add_fromto(spin, &spin->si_sal, items[1],
- STRCMP(items[2], "_") == 0 ? (char_u *)""
- : items[2]);
+ add_fromto(spin, &spin->si_sal, (char_u *)items[1],
+ strcmp(items[2], "_") == 0 ? (char_u *)""
+ : (char_u *)items[2]);
}
}
} else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2)
&& sofofrom == NULL) {
- sofofrom = getroom_save(spin, items[1]);
+ sofofrom = (char_u *)getroom_save(spin, (char_u *)items[1]);
} else if (is_aff_rule(items, itemcnt, "SOFOTO", 2)
&& sofoto == NULL) {
- sofoto = getroom_save(spin, items[1]);
- } else if (STRCMP(items[0], "COMMON") == 0) {
+ sofoto = (char_u *)getroom_save(spin, (char_u *)items[1]);
+ } else if (strcmp(items[0], "COMMON") == 0) {
int i;
for (i = 1; i < itemcnt; i++) {
if (HASHITEM_EMPTY(hash_find(&spin->si_commonwords, (char *)items[i]))) {
- p = vim_strsave(items[i]);
- hash_add(&spin->si_commonwords, p);
+ p = xstrdup(items[i]);
+ hash_add(&spin->si_commonwords, (char_u *)p);
}
}
} else {
@@ -2747,7 +2744,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
if (syllable != NULL) {
- aff_check_string(spin->si_syllable, syllable, "SYLLABLE");
+ aff_check_string((char *)spin->si_syllable, (char *)syllable, "SYLLABLE");
spin->si_syllable = syllable;
}
@@ -2758,15 +2755,15 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
} else if (!GA_EMPTY(&spin->si_sal)) {
smsg(_("Both SAL and SOFO lines in %s"), fname);
} else {
- aff_check_string(spin->si_sofofr, sofofrom, "SOFOFROM");
- aff_check_string(spin->si_sofoto, sofoto, "SOFOTO");
+ aff_check_string((char *)spin->si_sofofr, (char *)sofofrom, "SOFOFROM");
+ aff_check_string((char *)spin->si_sofoto, (char *)sofoto, "SOFOTO");
spin->si_sofofr = sofofrom;
spin->si_sofoto = sofoto;
}
}
if (midword != NULL) {
- aff_check_string(spin->si_midword, midword, "MIDWORD");
+ aff_check_string((char *)spin->si_midword, (char *)midword, "MIDWORD");
spin->si_midword = midword;
}
@@ -2775,11 +2772,11 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
return aff;
}
-// Returns true when items[0] equals "rulename", there are "mincount" items or
-// a comment is following after item "mincount".
-static bool is_aff_rule(char_u **items, int itemcnt, char *rulename, int mincount)
+/// @return true when items[0] equals "rulename", there are "mincount" items or
+/// a comment is following after item "mincount".
+static bool is_aff_rule(char **items, int itemcnt, char *rulename, int mincount)
{
- return STRCMP(items[0], rulename) == 0
+ return strcmp(items[0], rulename) == 0
&& (itemcnt == mincount
|| (itemcnt > mincount && items[mincount][0] == '#'));
}
@@ -2816,15 +2813,15 @@ static void aff_process_flags(afffile_T *affile, affentry_T *entry)
}
}
-// Returns true if "s" is the name of an info item in the affix file.
-static bool spell_info_item(char_u *s)
+/// @return true if "s" is the name of an info item in the affix file.
+static bool spell_info_item(char *s)
{
- return STRCMP(s, "NAME") == 0
- || STRCMP(s, "HOME") == 0
- || STRCMP(s, "VERSION") == 0
- || STRCMP(s, "AUTHOR") == 0
- || STRCMP(s, "EMAIL") == 0
- || STRCMP(s, "COPYRIGHT") == 0;
+ return strcmp(s, "NAME") == 0
+ || strcmp(s, "HOME") == 0
+ || strcmp(s, "VERSION") == 0
+ || strcmp(s, "AUTHOR") == 0
+ || strcmp(s, "EMAIL") == 0
+ || strcmp(s, "COPYRIGHT") == 0;
}
// Turn an affix flag name into a number, according to the FLAG type.
@@ -3016,23 +3013,23 @@ static void aff_check_number(int spinval, int affval, char *name)
}
}
-// Give a warning when "spinval" and "affval" strings are set and not the same.
-static void aff_check_string(char_u *spinval, char_u *affval, char *name)
+/// Give a warning when "spinval" and "affval" strings are set and not the same.
+static void aff_check_string(char *spinval, char *affval, char *name)
{
- if (spinval != NULL && STRCMP(spinval, affval) != 0) {
+ if (spinval != NULL && strcmp(spinval, affval) != 0) {
smsg(_("%s value differs from what is used in another .aff file"),
name);
}
}
-// Returns true if strings "s1" and "s2" are equal. Also consider both being
-// NULL as equal.
-static bool str_equal(char_u *s1, char_u *s2)
+/// @return true if strings "s1" and "s2" are equal. Also consider both being
+/// NULL as equal.
+static bool str_equal(char *s1, char *s2)
{
if (s1 == NULL || s2 == NULL) {
return s1 == s2;
}
- return STRCMP(s1, s2) == 0;
+ return strcmp(s1, s2) == 0;
}
// Add a from-to item to "gap". Used for REP and SAL items.
@@ -3043,15 +3040,15 @@ 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;
-static bool sal_to_bool(char_u *s)
+/// Converts a boolean argument in a SAL line to true or false;
+static bool sal_to_bool(char *s)
{
- return STRCMP(s, "1") == 0 || STRCMP(s, "true") == 0;
+ return strcmp(s, "1") == 0 || strcmp(s, "true") == 0;
}
// Free the structure filled by spell_read_aff().
@@ -3068,7 +3065,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 +3122,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 +3154,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);
@@ -3199,7 +3196,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
_("line %6d, word %6ld - %s"),
lnum, spin->si_foldwcount + spin->si_keepwcount, w);
msg_start();
- msg_outtrans_long_attr(message, 0);
+ msg_outtrans_long_attr((char *)message, 0);
msg_clr_eos();
msg_didout = false;
msg_col = 0;
@@ -3208,7 +3205,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 +3431,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 +3537,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 +3559,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 +3675,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 +3700,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 +3722,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 +3819,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 +3853,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 +3862,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 +3893,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 +3927,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 +3941,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 +3953,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 +3972,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 +3987,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 +4074,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 +4169,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 +4181,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 +4212,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 +4260,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;
@@ -4341,23 +4337,24 @@ static bool node_equal(wordnode_T *n1, wordnode_T *n2)
return p1 == NULL && p2 == NULL;
}
-// Function given to qsort() to sort the REP items on "from" string.
+/// Function given to qsort() to sort the REP items on "from" string.
static int rep_compare(const void *s1, const void *s2)
{
fromto_T *p1 = (fromto_T *)s1;
fromto_T *p2 = (fromto_T *)s2;
- return STRCMP(p1->ft_from, p2->ft_from);
+ return strcmp((char *)p1->ft_from, (char *)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 +4419,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 +4463,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 +4497,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 +4522,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 +4563,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 +4686,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 +4875,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 +4893,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,13 +4906,13 @@ 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..."));
+ spell_message(spin, _("Reading back spell file..."));
slang = spell_load_file(wfname, NULL, NULL, false);
if (slang == NULL) {
return;
@@ -4933,7 +4930,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 +4947,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 +5012,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 +5193,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,9 +5230,9 @@ 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);
+ char_u *line = (char_u *)ml_get_buf(spin->si_spellbuf, lnum, false);
size_t len = STRLEN(line) + 1;
if (fwrite(line, len, 1, fd) == 0) {
emsg(_(e_write));
@@ -5252,7 +5249,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 +5268,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,43 +5295,43 @@ 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]);
- if (fcount == 1 && len > 4 && STRCMP(fnames[0] + len - 4, ".add") == 0) {
+ if (fcount == 1 && len > 4 && strcmp(fnames[0] + len - 4, ".add") == 0) {
// For ":mkspell path/en.latin1.add" output file is
// "path/en.latin1.add.spl".
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) {
+ } 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);
@@ -5355,7 +5351,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,12 +5383,12 @@ 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;
vim_snprintf((char *)fname, MAXPATHL, "%s.aff", innames[i]);
- if (os_path_exists(fname)) {
+ if (os_path_exists((char *)fname)) {
// Read the .aff file. Will init "spin->si_conv" based on the
// "SET" line.
afile[i] = spell_read_aff(&spin, fname);
@@ -5424,7 +5420,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 +5430,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 +5455,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 +5478,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();
@@ -5503,7 +5499,7 @@ static void spell_message(const spellinfo_T *spin, char_u *str)
// ":[count]spellrare {word}"
void ex_spell(exarg_T *eap)
{
- spell_add_word((char_u *)eap->arg, (int)STRLEN(eap->arg),
+ spell_add_word((char_u *)eap->arg, (int)strlen(eap->arg),
eap->cmdidx == CMD_spellwrong ? SPELL_ADD_BAD :
eap->cmdidx == CMD_spellrare ? SPELL_ADD_RARE : SPELL_ADD_GOOD,
eap->forceit ? 0 : (int)eap->line2,
@@ -5527,14 +5523,14 @@ 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;
}
if (idx == 0) { // use internal wordlist
if (int_wordlist == NULL) {
- int_wordlist = vim_tempname();
+ int_wordlist = (char_u *)vim_tempname();
if (int_wordlist == NULL) {
return;
}
@@ -5553,7 +5549,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 +5663,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 +5677,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 +5694,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 +5708,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 +5722,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 +5753,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 +5777,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]
@@ -5815,7 +5809,7 @@ static int write_spell_prefcond(FILE *fd, garray_T *gap, size_t *fwv)
// <prefcond> : <condlen> <condstr>
char *p = ((char **)gap->ga_data)[i];
if (p != NULL) {
- size_t len = STRLEN(p);
+ size_t len = strlen(p);
if (fd != NULL) {
assert(len <= INT_MAX);
fputc((int)len, fd);
@@ -5846,7 +5840,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);
@@ -5878,7 +5872,7 @@ static void set_map_str(slang_T *lp, char_u *map)
utf_char2bytes(headc, b + cl + 1);
b[cl + 1 + headcl] = NUL;
hash = hash_hash((char_u *)b);
- hi = hash_lookup(&lp->sl_map_hash, (const char *)b, STRLEN(b), hash);
+ hi = hash_lookup(&lp->sl_map_hash, (const char *)b, strlen(b), hash);
if (HASHITEM_EMPTY(hi)) {
hash_add_item(&lp->sl_map_hash, hi, (char_u *)b, hash);
} else {
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
index b4a9bed437..16af1b72a3 100644
--- a/src/nvim/spellsuggest.c
+++ b/src/nvim/spellsuggest.c
@@ -65,7 +65,7 @@ typedef struct suginfo_S {
/// One word suggestion. Used in "si_ga".
typedef struct {
- char_u *st_word; ///< suggested word, allocated string
+ char *st_word; ///< suggested word, allocated string
int st_wordlen; ///< STRLEN(st_word)
int st_orglen; ///< length of replaced text
int st_score; ///< lower is better
@@ -354,13 +354,13 @@ int spell_check_sps(void)
{
char *p;
char *s;
- char_u buf[MAXPATHL];
+ char buf[MAXPATHL];
int f;
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;
@@ -370,11 +370,11 @@ int spell_check_sps(void)
if (*s != NUL && !ascii_isdigit(*s)) {
f = -1;
}
- } else if (STRCMP(buf, "best") == 0) {
+ } else if (strcmp(buf, "best") == 0) {
f = SPS_BEST;
- } else if (STRCMP(buf, "fast") == 0) {
+ } else if (strcmp(buf, "fast") == 0) {
f = SPS_FAST;
- } else if (STRCMP(buf, "double") == 0) {
+ } else if (strcmp(buf, "double") == 0) {
f = SPS_DOUBLE;
} else if (STRNCMP(buf, "expr:", 5) != 0
&& STRNCMP(buf, "file:", 5) != 0
@@ -407,7 +407,7 @@ int spell_check_sps(void)
/// When "count" is non-zero use that suggestion.
void spell_suggest(int count)
{
- char_u *line;
+ char *line;
pos_T prev_cursor = curwin->w_cursor;
char_u wcopy[MAXWLEN + 2];
char_u *p;
@@ -454,9 +454,9 @@ void spell_suggest(int count)
// cursor.
curwin->w_cursor = prev_cursor;
line = get_cursor_line_ptr();
- p = line + curwin->w_cursor.col;
+ p = (char_u *)line + curwin->w_cursor.col;
// Backup to before start of word.
- while (p > line && spell_iswordp_nmw(p, curwin)) {
+ while (p > (char_u *)line && spell_iswordp_nmw(p, curwin)) {
MB_PTR_BACK(line, p);
}
// Forward to start of word.
@@ -468,7 +468,7 @@ void spell_suggest(int count)
beep_flush();
return;
}
- curwin->w_cursor.col = (colnr_T)(p - line);
+ curwin->w_cursor.col = (colnr_T)(p - (char_u *)line);
}
// Get the word and its length.
@@ -477,7 +477,7 @@ void spell_suggest(int count)
need_cap = check_need_cap(curwin->w_cursor.lnum, curwin->w_cursor.col);
// Make a copy of current line since autocommands may free the line.
- line = vim_strsave(get_cursor_line_ptr());
+ line = xstrdup(get_cursor_line_ptr());
spell_suggest_timeout = 5000;
// Get the list of suggestions. Limit to 'lines' - 2 or the number in
@@ -487,7 +487,7 @@ void spell_suggest(int count)
} else {
limit = sps_limit;
}
- spell_find_suggest(line + curwin->w_cursor.col, badlen, &sug, limit,
+ spell_find_suggest((char_u *)line + curwin->w_cursor.col, badlen, &sug, limit,
true, need_cap, true);
if (GA_EMPTY(&sug.su_ga)) {
@@ -533,7 +533,7 @@ void spell_suggest(int count)
}
vim_snprintf((char *)IObuff, IOSIZE, "%2d", i + 1);
if (cmdmsg_rl) {
- rl_mirror(IObuff);
+ rl_mirror((char_u *)IObuff);
}
msg_puts((const char *)IObuff);
@@ -559,7 +559,7 @@ void spell_suggest(int count)
}
if (cmdmsg_rl) {
// Mirror the numbers, but keep the leading space.
- rl_mirror(IObuff + 1);
+ rl_mirror((char_u *)IObuff + 1);
}
msg_advance(30);
msg_puts((const char *)IObuff);
@@ -593,20 +593,20 @@ void spell_suggest(int count)
if (sug.su_badlen > stp->st_orglen) {
// Replacing less than "su_badlen", append the remainder to
// repl_to.
- repl_from = vim_strnsave(sug.su_badptr, (size_t)sug.su_badlen);
+ repl_from = xstrnsave((char *)sug.su_badptr, (size_t)sug.su_badlen);
vim_snprintf((char *)IObuff, IOSIZE, "%s%.*s", stp->st_word,
sug.su_badlen - stp->st_orglen,
sug.su_badptr + stp->st_orglen);
- repl_to = vim_strsave(IObuff);
+ repl_to = xstrdup((char *)IObuff);
} else {
// Replacing su_badlen or more, use the whole word.
- repl_from = vim_strnsave(sug.su_badptr, (size_t)stp->st_orglen);
- repl_to = vim_strsave(stp->st_word);
+ repl_from = xstrnsave((char *)sug.su_badptr, (size_t)stp->st_orglen);
+ repl_to = xstrdup(stp->st_word);
}
// Replace the word.
p = xmalloc(STRLEN(line) - (size_t)stp->st_orglen + (size_t)stp->st_wordlen + 1);
- c = (int)(sug.su_badptr - line);
+ c = (int)(sug.su_badptr - (char_u *)line);
memmove(p, line, (size_t)c);
STRCPY(p + c, stp->st_word);
STRCAT(p, sug.su_badptr + stp->st_orglen);
@@ -678,7 +678,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma
char_u buf[MAXPATHL];
char *p;
bool do_combine = false;
- char_u *sps_copy;
+ char *sps_copy;
static bool expr_busy = false;
int c;
langp_T *lp;
@@ -748,7 +748,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma
c = utf_ptr2char((char *)su->su_badptr);
if (!SPELL_ISUPPER(c) && attr == HLF_COUNT) {
make_case_word(su->su_badword, buf, WF_ONECAP);
- add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE,
+ add_suggestion(su, &su->su_ga, (char *)buf, su->su_badlen, SCORE_ICASE,
0, true, su->su_sallang, false);
}
@@ -758,10 +758,10 @@ 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 = xstrdup(p_sps);
// Loop over the items in 'spellsuggest'.
- for (p = (char *)sps_copy; *p != NUL;) {
+ for (p = sps_copy; *p != NUL;) {
copy_option_part(&p, (char *)buf, MAXPATHL, ",");
if (STRNCMP(buf, "expr:", 5) == 0) {
@@ -814,7 +814,7 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr)
// Get the word and the score from the items.
score = get_spellword(TV_LIST_ITEM_TV(li)->vval.v_list, &p);
if (score >= 0 && score <= su->su_maxscore) {
- add_suggestion(su, &su->su_ga, (const char_u *)p, su->su_badlen,
+ add_suggestion(su, &su->su_ga, p, su->su_badlen,
score, 0, true, su->su_sallang, false);
}
}
@@ -864,7 +864,7 @@ static void spell_suggest_file(suginfo_T *su, char_u *fname)
p = cword;
}
- add_suggestion(su, &su->su_ga, p, su->su_badlen,
+ add_suggestion(su, &su->su_ga, (char *)p, su->su_badlen,
SCORE_FILE, 0, true, su->su_sallang, false);
}
}
@@ -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) {
@@ -985,7 +985,7 @@ static void suggest_try_special(suginfo_T *su)
// Give a soundalike score of 0, compute the score as if deleting one
// character.
- add_suggestion(su, &su->su_ga, word, su->su_badlen,
+ add_suggestion(su, &su->su_ga, (char *)word, su->su_badlen,
RESCORE(SCORE_REP, 0), 0, true, su->su_sallang, false);
}
}
@@ -1114,7 +1114,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
{
char_u tword[MAXWLEN]; // good word collected so far
trystate_T stack[MAXWLEN];
- char_u preword[MAXWLEN * 3] = { 0 }; // word found with proper case;
+ char preword[MAXWLEN * 3] = { 0 }; // word found with proper case;
// concatenation of prefix compound
// words and split word. NUL terminated
// when going deeper but not when coming
@@ -1241,7 +1241,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// and make find_keepcap_word() works.
tword[sp->ts_twordlen] = NUL;
make_case_word(tword + sp->ts_splitoff,
- preword + sp->ts_prewordlen, flags);
+ (char_u *)preword + sp->ts_prewordlen, flags);
sp->ts_prewordlen = (char_u)STRLEN(preword);
sp->ts_splitoff = sp->ts_twordlen;
}
@@ -1326,11 +1326,11 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
sp->ts_fidx - sp->ts_splitfidx) == 0) {
preword[sp->ts_prewordlen] = NUL;
newscore = score_wordcount_adj(slang, sp->ts_score,
- preword + sp->ts_prewordlen,
+ (char_u *)preword + sp->ts_prewordlen,
sp->ts_prewordlen > 0);
// Add the suggestion if the score isn't too bad.
if (newscore <= su->su_maxscore) {
- add_suggestion(su, &su->su_ga, preword,
+ add_suggestion(su, &su->su_ga, (char *)preword,
sp->ts_splitfidx - repextra,
newscore, 0, false,
lp->lp_sallang, false);
@@ -1362,15 +1362,15 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
sp->ts_twordlen - sp->ts_splitoff + 1);
// Verify CHECKCOMPOUNDPATTERN rules.
- if (match_checkcompoundpattern(preword, sp->ts_prewordlen,
+ if (match_checkcompoundpattern((char_u *)preword, sp->ts_prewordlen,
&slang->sl_comppat)) {
compound_ok = false;
}
if (compound_ok) {
- p = preword;
- while (*skiptowhite(p) != NUL) {
- p = (char_u *)skipwhite((char *)skiptowhite(p));
+ p = (char_u *)preword;
+ while (*skiptowhite((char *)p) != NUL) {
+ p = (char_u *)skipwhite(skiptowhite((char *)p));
}
if (fword_ends && !can_compound(slang, p,
compflags + sp->ts_compsplit)) {
@@ -1381,7 +1381,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
}
// Get pointer to last char of previous word.
- p = preword + sp->ts_prewordlen;
+ p = (char_u *)preword + sp->ts_prewordlen;
MB_PTR_BACK(preword, p);
}
}
@@ -1394,7 +1394,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
} else if (flags & WF_KEEPCAP) {
// Must find the word in the keep-case tree.
find_keepcap_word(slang, tword + sp->ts_splitoff,
- preword + sp->ts_prewordlen);
+ (char_u *)preword + sp->ts_prewordlen);
} else {
// Include badflags: If the badword is onecap or allcap
// use that for the goodword too. But if the badword is
@@ -1413,14 +1413,14 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
c &= ~WF_ONECAP;
}
make_case_word(tword + sp->ts_splitoff,
- preword + sp->ts_prewordlen, c);
+ (char_u *)preword + sp->ts_prewordlen, c);
}
if (!soundfold) {
// Don't use a banned word. It may appear again as a good
// word, thus remember it.
if (flags & WF_BANNED) {
- add_banned(su, preword + sp->ts_prewordlen);
+ add_banned(su, (char_u *)preword + sp->ts_prewordlen);
break;
}
if ((sp->ts_complen == sp->ts_compsplit
@@ -1445,7 +1445,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
}
if (!spell_valid_case(su->su_badflags,
- captype(preword + sp->ts_prewordlen, NULL))) {
+ captype((char_u *)preword + sp->ts_prewordlen, NULL))) {
newscore += SCORE_ICASE;
}
}
@@ -1457,7 +1457,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
&& compound_ok) {
// The badword also ends: add suggestions.
#ifdef DEBUG_TRIEWALK
- if (soundfold && STRCMP(preword, "smwrd") == 0) {
+ if (soundfold && strcmp(preword, "smwrd") == 0) {
int j;
// print the stack of changes that brought us here
@@ -1470,14 +1470,14 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
if (soundfold) {
// For soundfolded words we need to find the original
// words, the edit distance and then add them.
- add_sound_suggest(su, preword, sp->ts_score, lp);
+ add_sound_suggest(su, (char_u *)preword, sp->ts_score, lp);
} else if (sp->ts_fidx > 0) {
// Give a penalty when changing non-word char to word
// char, e.g., "thes," -> "these".
p = fword + sp->ts_fidx;
MB_PTR_BACK(fword, p);
if (!spell_iswordp(p, curwin) && *preword != NUL) {
- p = preword + STRLEN(preword);
+ p = (char_u *)preword + STRLEN(preword);
MB_PTR_BACK(preword, p);
if (spell_iswordp(p, curwin)) {
newscore += SCORE_NONWORD;
@@ -1487,25 +1487,25 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// Give a bonus to words seen before.
score = score_wordcount_adj(slang,
sp->ts_score + newscore,
- preword + sp->ts_prewordlen,
+ (char_u *)preword + sp->ts_prewordlen,
sp->ts_prewordlen > 0);
// Add the suggestion if the score isn't too bad.
if (score <= su->su_maxscore) {
- add_suggestion(su, &su->su_ga, preword,
+ add_suggestion(su, &su->su_ga, (char *)preword,
sp->ts_fidx - repextra,
score, 0, false, lp->lp_sallang, false);
if (su->su_badflags & WF_MIXCAP) {
// We really don't know if the word should be
// upper or lower case, add both.
- c = captype(preword, NULL);
+ c = captype((char_u *)preword, NULL);
if (c == 0 || c == WF_ALLCAP) {
make_case_word(tword + sp->ts_splitoff,
- preword + sp->ts_prewordlen,
+ (char_u *)preword + sp->ts_prewordlen,
c == 0 ? WF_ALLCAP : 0);
- add_suggestion(su, &su->su_ga, preword,
+ add_suggestion(su, &su->su_ga, (char *)preword,
sp->ts_fidx - repextra,
score + SCORE_ICASE, 0, false,
lp->lp_sallang, false);
@@ -1589,9 +1589,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
&& (flags & WF_NEEDCOMP)) {
break;
}
- p = preword;
- while (*skiptowhite(p) != NUL) {
- p = (char_u *)skipwhite((char *)skiptowhite(p));
+ p = (char_u *)preword;
+ while (*skiptowhite((char *)p) != NUL) {
+ p = (char_u *)skipwhite(skiptowhite((char *)p));
}
if (sp->ts_complen > sp->ts_compsplit
&& !can_compound(slang, p,
@@ -1607,7 +1607,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// Give a bonus to words seen before.
newscore = score_wordcount_adj(slang, newscore,
- preword + sp->ts_prewordlen, true);
+ (char_u *)preword + sp->ts_prewordlen, true);
}
if (TRY_DEEPER(su, stack, depth, newscore)) {
@@ -2494,7 +2494,7 @@ static void score_comp_sal(suginfo_T *su)
if (score < SCORE_MAXMAX) {
// Add the suggestion.
sstp = &SUG(su->su_sga, su->su_sga.ga_len);
- sstp->st_word = vim_strsave(stp->st_word);
+ sstp->st_word = xstrdup(stp->st_word);
sstp->st_wordlen = stp->st_wordlen;
sstp->st_score = score;
sstp->st_altscore = 0;
@@ -2515,8 +2515,8 @@ static void score_combine(suginfo_T *su)
garray_T *gap;
langp_T *lp;
suggest_T *stp;
- char_u *p;
- char_u badsound[MAXWLEN];
+ char *p;
+ char badsound[MAXWLEN];
int round;
slang_T *slang = NULL;
@@ -2526,11 +2526,11 @@ static void score_combine(suginfo_T *su)
if (!GA_EMPTY(&lp->lp_slang->sl_sal)) {
// soundfold the bad word
slang = lp->lp_slang;
- spell_soundfold(slang, su->su_fbadword, true, badsound);
+ spell_soundfold(slang, su->su_fbadword, true, (char_u *)badsound);
for (int i = 0; i < su->su_ga.ga_len; i++) {
stp = &SUG(su->su_ga, i);
- stp->st_altscore = stp_sal_score(stp, su, slang, badsound);
+ stp->st_altscore = stp_sal_score(stp, su, slang, (char_u *)badsound);
if (stp->st_altscore == SCORE_MAXMAX) {
stp->st_score = (stp->st_score * 3 + SCORE_BIG) / 4;
} else {
@@ -2551,8 +2551,7 @@ static void score_combine(suginfo_T *su)
// Add the alternate score to su_sga.
for (int i = 0; i < su->su_sga.ga_len; i++) {
stp = &SUG(su->su_sga, i);
- stp->st_altscore = spell_edit_score(slang,
- su->su_badword, stp->st_word);
+ stp->st_altscore = spell_edit_score(slang, su->su_badword, (char_u *)stp->st_word);
if (stp->st_score == SCORE_MAXMAX) {
stp->st_score = (SCORE_BIG * 7 + stp->st_altscore) / 8;
} else {
@@ -2582,7 +2581,7 @@ static void score_combine(suginfo_T *su)
p = SUG(*gap, i).st_word;
int j;
for (j = 0; j < ga.ga_len; j++) {
- if (STRCMP(stp[j].st_word, p) == 0) {
+ if (strcmp(stp[j].st_word, p) == 0) {
break;
}
}
@@ -2637,7 +2636,7 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u *
// space.
if (ascii_iswhite(su->su_badptr[su->su_badlen])
&& *skiptowhite(stp->st_word) == NUL) {
- for (p = fword; *(p = skiptowhite(p)) != NUL;) {
+ for (p = fword; *(p = (char_u *)skiptowhite((char *)p)) != NUL;) {
STRMOVE(p, p + 1);
}
}
@@ -2654,13 +2653,13 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u *
su->su_badptr + su->su_badlen - lendiff, lendiff + 1);
pgood = goodword;
} else {
- pgood = stp->st_word;
+ pgood = (char_u *)stp->st_word;
}
// Sound-fold the word and compute the score for the difference.
spell_soundfold(slang, pgood, false, goodsound);
- return soundalike_score(goodsound, pbad);
+ return soundalike_score((char *)goodsound, (char *)pbad);
}
/// structure used to store soundfolded words that add_sound_suggest() has
@@ -2807,7 +2806,7 @@ static void add_sound_suggest(suginfo_T *su, char_u *goodword, int score, langp_
}
// Go over the list of good words that produce this soundfold word
- nrline = ml_get_buf(slang->sl_sugbuf, (linenr_T)sfwordnr + 1, false);
+ nrline = (char_u *)ml_get_buf(slang->sl_sugbuf, (linenr_T)sfwordnr + 1, false);
orgnr = 0;
while (*nrline != NUL) {
// The wordnr was stored in a minimal nr of bytes as an offset to the
@@ -2883,7 +2882,7 @@ badword:
if (sps_flags & SPS_DOUBLE) {
// Add the suggestion if the score isn't too bad.
if (score <= su->su_maxscore) {
- add_suggestion(su, &su->su_sga, p, su->su_badlen,
+ add_suggestion(su, &su->su_sga, (char *)p, su->su_badlen,
score, 0, false, slang, false);
}
} else {
@@ -2931,7 +2930,7 @@ badword:
// Add the suggestion if the score isn't too bad.
goodscore = RESCORE(goodscore, score);
if (goodscore <= su->su_sfmaxscore) {
- add_suggestion(su, &su->su_ga, p, su->su_badlen,
+ add_suggestion(su, &su->su_ga, (char *)p, su->su_badlen,
goodscore, score, true, slang, true);
}
}
@@ -3061,7 +3060,7 @@ static bool similar_chars(slang_T *slang, int c1, int c2)
/// @param had_bonus value for st_had_bonus
/// @param slang language for sound folding
/// @param maxsf su_maxscore applies to soundfold score, su_sfmaxscore to the total score.
-static void add_suggestion(suginfo_T *su, garray_T *gap, const char_u *goodword, int badlenarg,
+static void add_suggestion(suginfo_T *su, garray_T *gap, const char *goodword, int badlenarg,
int score, int altscore, bool had_bonus, slang_T *slang, bool maxsf)
{
int goodlen; // len of goodword changed
@@ -3071,7 +3070,7 @@ static void add_suggestion(suginfo_T *su, garray_T *gap, const char_u *goodword,
// Minimize "badlen" for consistency. Avoids that changing "the the" to
// "thee the" is added next to changing the first "the" the "thee".
- const char_u *pgood = goodword + STRLEN(goodword);
+ const char *pgood = goodword + STRLEN(goodword);
char_u *pbad = su->su_badptr + badlenarg;
for (;;) {
goodlen = (int)(pgood - goodword);
@@ -3100,7 +3099,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) {
@@ -3144,7 +3143,7 @@ static void add_suggestion(suginfo_T *su, garray_T *gap, const char_u *goodword,
if (i < 0) {
// Add a suggestion.
stp = GA_APPEND_VIA_PTR(suggest_T, gap);
- stp->st_word = vim_strnsave(goodword, (size_t)goodlen);
+ stp->st_word = xstrnsave(goodword, (size_t)goodlen);
stp->st_wordlen = goodlen;
stp->st_score = score;
stp->st_altscore = altscore;
@@ -3307,15 +3306,15 @@ static int cleanup_suggestions(garray_T *gap, int maxscore, int keep)
///
/// @param goodstart sound-folded good word
/// @param badstart sound-folded bad word
-static int soundalike_score(char_u *goodstart, char_u *badstart)
+static int soundalike_score(char *goodstart, char *badstart)
{
- char_u *goodsound = goodstart;
- char_u *badsound = badstart;
+ char *goodsound = goodstart;
+ char *badsound = badstart;
int goodlen;
int badlen;
int n;
- char_u *pl, *ps;
- char_u *pl2, *ps2;
+ char *pl, *ps;
+ char *pl2, *ps2;
int score = 0;
// Adding/inserting "*" at the start (word starts with vowel) shouldn't be
@@ -3380,7 +3379,7 @@ static int soundalike_score(char_u *goodstart, char_u *badstart)
ps++;
}
// strings must be equal after second delete
- if (STRCMP(pl + 1, ps) == 0) {
+ if (strcmp(pl + 1, ps) == 0) {
return score + SCORE_DEL * 2;
}
@@ -3404,12 +3403,12 @@ static int soundalike_score(char_u *goodstart, char_u *badstart)
// 2: delete then swap, then rest must be equal
if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
- && STRCMP(pl2 + 2, ps2 + 2) == 0) {
+ && strcmp(pl2 + 2, ps2 + 2) == 0) {
return score + SCORE_DEL + SCORE_SWAP;
}
// 3: delete then substitute, then the rest must be equal
- if (STRCMP(pl2 + 1, ps2 + 1) == 0) {
+ if (strcmp(pl2 + 1, ps2 + 1) == 0) {
return score + SCORE_DEL + SCORE_SUBST;
}
@@ -3422,7 +3421,7 @@ static int soundalike_score(char_u *goodstart, char_u *badstart)
ps2++;
}
// delete a char and then strings must be equal
- if (STRCMP(pl2 + 1, ps2) == 0) {
+ if (strcmp(pl2 + 1, ps2) == 0) {
return score + SCORE_SWAP + SCORE_DEL;
}
}
@@ -3435,7 +3434,7 @@ static int soundalike_score(char_u *goodstart, char_u *badstart)
ps2++;
}
// delete a char and then strings must be equal
- if (STRCMP(pl2 + 1, ps2) == 0) {
+ if (strcmp(pl2 + 1, ps2) == 0) {
return score + SCORE_SUBST + SCORE_DEL;
}
@@ -3463,12 +3462,12 @@ static int soundalike_score(char_u *goodstart, char_u *badstart)
}
// 3: swap and swap again
if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
- && STRCMP(pl2 + 2, ps2 + 2) == 0) {
+ && strcmp(pl2 + 2, ps2 + 2) == 0) {
return score + SCORE_SWAP + SCORE_SWAP;
}
// 4: swap and substitute
- if (STRCMP(pl2 + 1, ps2 + 1) == 0) {
+ if (strcmp(pl2 + 1, ps2 + 1) == 0) {
return score + SCORE_SWAP + SCORE_SUBST;
}
}
@@ -3486,12 +3485,12 @@ static int soundalike_score(char_u *goodstart, char_u *badstart)
// 6: substitute and swap
if (pl2[0] == ps2[1] && pl2[1] == ps2[0]
- && STRCMP(pl2 + 2, ps2 + 2) == 0) {
+ && strcmp(pl2 + 2, ps2 + 2) == 0) {
return score + SCORE_SUBST + SCORE_SWAP;
}
// 7: substitute and substitute
- if (STRCMP(pl2 + 1, ps2 + 1) == 0) {
+ if (strcmp(pl2 + 1, ps2 + 1) == 0) {
return score + SCORE_SUBST + SCORE_SUBST;
}
@@ -3502,7 +3501,7 @@ static int soundalike_score(char_u *goodstart, char_u *badstart)
pl2++;
ps2++;
}
- if (STRCMP(pl2 + 1, ps2) == 0) {
+ if (strcmp(pl2 + 1, ps2) == 0) {
return score + SCORE_INS + SCORE_DEL;
}
@@ -3513,7 +3512,7 @@ static int soundalike_score(char_u *goodstart, char_u *badstart)
pl2++;
ps2++;
}
- if (STRCMP(pl2, ps2 + 1) == 0) {
+ if (strcmp(pl2, ps2 + 1) == 0) {
return score + SCORE_INS + SCORE_DEL;
}
diff --git a/src/nvim/state.c b/src/nvim/state.c
index 61740800a1..458eed960f 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -237,7 +237,7 @@ void may_trigger_modechanged(void)
char pattern_buf[2 * MODE_MAX_LENGTH];
get_mode(curr_mode);
- if (STRCMP(curr_mode, last_mode) == 0) {
+ if (strcmp(curr_mode, last_mode) == 0) {
return;
}
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index e868a79b9a..5f686ef96f 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);
@@ -426,7 +426,7 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
int len;
int fillchar;
char buf[MAXPATHL];
- char_u *stl;
+ char *stl;
char *p;
stl_hlrec_t *hltab;
StlClickRecord *tabtab;
@@ -455,7 +455,7 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
maxwidth = Columns;
use_sandbox = was_set_insecurely(wp, "tabline", 0);
} else if (draw_winbar) {
- stl = (char_u *)((*wp->w_p_wbr != NUL) ? wp->w_p_wbr : p_wbr);
+ stl = ((*wp->w_p_wbr != NUL) ? wp->w_p_wbr : p_wbr);
row = -1; // row zero is first row of text
col = 0;
grid = &wp->w_grid;
@@ -497,7 +497,7 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
if (*++stl == '-') {
stl++;
}
- if (atoi((char *)stl)) {
+ if (atoi(stl)) {
while (ascii_isdigit(*stl)) {
stl++;
}
@@ -544,9 +544,9 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
// Make a copy, because the statusline may include a function call that
// might change the option value and free the memory.
- stl = vim_strsave(stl);
+ stl = xstrdup(stl);
width =
- build_stl_str_hl(ewp, buf, sizeof(buf), (char *)stl, use_sandbox,
+ build_stl_str_hl(ewp, buf, sizeof(buf), stl, use_sandbox,
fillchar, maxwidth, &hltab, &tabtab);
xfree(stl);
ewp->w_p_crb = p_crb_save;
@@ -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;
}
@@ -712,7 +711,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san
}
// Get line & check if empty (cursorpos will show "0-1").
- const char *line_ptr = (char *)ml_get_buf(wp->w_buffer, lnum, false);
+ const char *line_ptr = ml_get_buf(wp->w_buffer, lnum, false);
bool empty_line = (*line_ptr == NUL);
// Get the byte value now, in case we need it below. This is more
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 78312c738c..ee6172e7fc 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -49,53 +49,31 @@
#include "nvim/vim.h"
#include "nvim/window.h"
-/// Copy "string" into newly allocated memory.
-char_u *vim_strsave(const char_u *string)
- FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
-{
- return (char_u *)xstrdup((char *)string);
-}
-
/// Copy up to `len` bytes of `string` into newly allocated memory and
/// terminate with a NUL. The allocated memory always has size `len + 1`, even
/// when `string` is shorter.
-char_u *vim_strnsave(const char_u *string, size_t len)
- FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
-{
- // strncpy is intentional: some parts of Vim use `string` shorter than `len`
- // and expect the remainder to be zeroed out.
- return (char_u *)strncpy(xmallocz(len), (char *)string, len);
-}
-
-/// A clone of vim_strnsave() that uses char* instead of char_u*
char *xstrnsave(const char *string, size_t len)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
return strncpy(xmallocz(len), string, len); // NOLINT(runtime/printf)
}
-/*
- * Same as vim_strsave(), but any characters found in esc_chars are preceded
- * by a backslash.
- */
+// Same as vim_strsave(), but any characters found in esc_chars are preceded
+// by a backslash.
char_u *vim_strsave_escaped(const char_u *string, const char_u *esc_chars)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
return vim_strsave_escaped_ext(string, esc_chars, '\\', false);
}
-/*
- * Same as vim_strsave_escaped(), but when "bsl" is true also escape
- * characters where rem_backslash() would remove the backslash.
- * Escape the characters with "cc".
- */
+// Same as vim_strsave_escaped(), but when "bsl" is true also escape
+// characters where rem_backslash() would remove the backslash.
+// Escape the characters with "cc".
char_u *vim_strsave_escaped_ext(const char_u *string, const char_u *esc_chars, char_u cc, bool bsl)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
- /*
- * First count the number of backslashes required.
- * Then allocate the memory and insert them.
- */
+ // First count the number of backslashes required.
+ // Then allocate the memory and insert them.
size_t length = 1; // count the trailing NUL
for (const char_u *p = string; *p; p++) {
const size_t l = (size_t)(utfc_ptr2len((char *)p));
@@ -104,10 +82,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 +98,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;
@@ -178,16 +156,14 @@ char *vim_strnsave_unquoted(const char *const string, const size_t length)
return ret;
}
-/*
- * Escape "string" for use as a shell argument with system().
- * This uses single quotes, except when we know we need to use double quotes
- * (MS-Windows without 'shellslash' set).
- * Escape a newline, depending on the 'shell' option.
- * When "do_special" is true also replace "!", "%", "#" and things starting
- * with "<" like "<cfile>".
- * When "do_newline" is false do not escape newline unless it is csh shell.
- * Returns the result in allocated memory.
- */
+// Escape "string" for use as a shell argument with system().
+// This uses single quotes, except when we know we need to use double quotes
+// (MS-Windows without 'shellslash' set).
+// Escape a newline, depending on the 'shell' option.
+// When "do_special" is true also replace "!", "%", "#" and things starting
+// with "<" like "<cfile>".
+// When "do_newline" is false do not escape newline unless it is csh shell.
+// Returns the result in allocated memory.
char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_newline)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
@@ -197,10 +173,10 @@ char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_n
int csh_like;
bool fish_like;
- /* Only csh and similar shells expand '!' within single quotes. For sh and
- * the like we must not put a backslash before it, it will be taken
- * literally. If do_special is set the '!' will be escaped twice.
- * Csh also needs to have "\n" escaped twice when do_special is set. */
+ // Only csh and similar shells expand '!' within single quotes. For sh and
+ // the like we must not put a backslash before it, it will be taken
+ // literally. If do_special is set the '!' will be escaped twice.
+ // Csh also needs to have "\n" escaped twice when do_special is set.
csh_like = csh_like_shell();
// Fish shell uses '\' as an escape character within single quotes, so '\'
@@ -222,13 +198,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) {
@@ -304,35 +280,29 @@ char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_n
return escaped_string;
}
-/*
- * Like vim_strsave(), but make all characters uppercase.
- * This uses ASCII lower-to-upper case translation, language independent.
- */
+// Like vim_strsave(), but make all characters uppercase.
+// This uses ASCII lower-to-upper case translation, language independent.
char_u *vim_strsave_up(const char_u *string)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
- char_u *p1;
+ char *p1;
- p1 = vim_strsave(string);
- vim_strup(p1);
- return p1;
+ p1 = xstrdup((char *)string);
+ vim_strup((char_u *)p1);
+ return (char_u *)p1;
}
-/*
- * Like vim_strnsave(), but make all characters uppercase.
- * This uses ASCII lower-to-upper case translation, language independent.
- */
-char_u *vim_strnsave_up(const char_u *string, size_t len)
+/// Like xstrnsave(), but make all characters uppercase.
+/// This uses ASCII lower-to-upper case translation, language independent.
+char *vim_strnsave_up(const char *string, size_t len)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
- char_u *p1 = vim_strnsave(string, len);
- vim_strup(p1);
+ char *p1 = xstrnsave(string, len);
+ vim_strup((char_u *)p1);
return p1;
}
-/*
- * ASCII lower-to-upper case translation, language independent.
- */
+// ASCII lower-to-upper case translation, language independent.
void vim_strup(char_u *p)
FUNC_ATTR_NONNULL_ALL
{
@@ -386,9 +356,7 @@ char *strcase_save(const char *const orig, bool upper)
return res;
}
-/*
- * delete spaces at the end of a string
- */
+// delete spaces at the end of a string
void del_trailing_spaces(char_u *ptr)
FUNC_ATTR_NONNULL_ALL
{
@@ -413,11 +381,9 @@ size_t xstrnlen(const char *s, size_t n)
#endif
#if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP))
-/*
- * Compare two strings, ignoring case, using current locale.
- * Doesn't work for multi-byte characters.
- * return 0 for match, < 0 for smaller, > 0 for bigger
- */
+// Compare two strings, ignoring case, using current locale.
+// Doesn't work for multi-byte characters.
+// return 0 for match, < 0 for smaller, > 0 for bigger
int vim_stricmp(const char *s1, const char *s2)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
{
@@ -439,11 +405,9 @@ int vim_stricmp(const char *s1, const char *s2)
#endif
#if (!defined(HAVE_STRNCASECMP) && !defined(HAVE_STRNICMP))
-/*
- * Compare two strings, for length "len", ignoring case, using current locale.
- * Doesn't work for multi-byte characters.
- * return 0 for match, < 0 for smaller, > 0 for bigger
- */
+// Compare two strings, for length "len", ignoring case, using current locale.
+// Doesn't work for multi-byte characters.
+// return 0 for match, < 0 for smaller, > 0 for bigger
int vim_strnicmp(const char *s1, const char *s2, size_t len)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
{
@@ -488,9 +452,7 @@ char *vim_strchr(const char *const string, const int c)
}
}
-/*
- * Sort an array of strings.
- */
+// Sort an array of strings.
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "strings.c.generated.h"
@@ -498,25 +460,23 @@ char *vim_strchr(const char *const string, const int c)
static int sort_compare(const void *s1, const void *s2)
FUNC_ATTR_NONNULL_ALL
{
- return STRCMP(*(char **)s1, *(char **)s2);
+ return strcmp(*(char **)s1, *(char **)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);
}
-/*
- * Return true if string "s" contains a non-ASCII character (128 or higher).
- * When "s" is NULL false is returned.
- */
+// Return true if string "s" contains a non-ASCII character (128 or higher).
+// When "s" is NULL false is returned.
bool has_non_ascii(const char_u *s)
FUNC_ATTR_PURE
{
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 +500,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 +1469,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..ce952147f7 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -1,9 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * syntax.c: code for syntax highlighting
- */
+// syntax.c: code for syntax highlighting
#include <assert.h>
#include <ctype.h>
@@ -93,22 +91,20 @@ typedef struct syn_pattern {
int16_t *sp_cont_list; // cont. group IDs, if non-zero
int16_t *sp_next_list; // next group IDs, if non-zero
struct sp_syn sp_syn; // struct passed to in_id_list()
- char_u *sp_pattern; // regexp to match, pattern
+ char *sp_pattern; // regexp to match, pattern
regprog_T *sp_prog; // regexp to match, program
syn_time_T sp_time;
} synpat_T;
typedef struct syn_cluster_S {
char_u *scl_name; // syntax cluster name
- char_u *scl_name_u; // uppercase of scl_name
+ char *scl_name_u; // uppercase of scl_name
int16_t *scl_list; // IDs in this syntax cluster
} syn_cluster_T;
-/*
- * For the current state we need to remember more than just the idx.
- * When si_m_endpos.lnum is 0, the items other than si_idx are unknown.
- * (The end positions have the column number of the next char)
- */
+// For the current state we need to remember more than just the idx.
+// When si_m_endpos.lnum is 0, the items other than si_idx are unknown.
+// (The end positions have the column number of the next char)
typedef struct state_item {
int si_idx; // index of syntax pattern or
// KEYWORD_IDX
@@ -133,10 +129,8 @@ typedef struct state_item {
// pattern
} stateitem_T;
-/*
- * Struct to reduce the number of arguments to get_syn_options(), it's used
- * very often.
- */
+// Struct to reduce the number of arguments to get_syn_options(), it's used
+// very often.
typedef struct {
int flags; // flags for contained and transparent
bool keyword; // true for ":syn keyword"
@@ -184,9 +178,7 @@ static char *(spo_name_tab[SPO_COUNT]) =
#define NONE_IDX (-2) // value of sp_sync_idx for "NONE"
-/*
- * Flags for b_syn_sync_flags:
- */
+// Flags for b_syn_sync_flags:
#define SF_CCOMMENT 0x01 // sync on a C-style comment
#define SF_MATCH 0x02 // sync by matching a pattern
@@ -194,9 +186,7 @@ static char *(spo_name_tab[SPO_COUNT]) =
#define MAXKEYWLEN 80 // maximum length of a keyword
-/*
- * The attributes of the syntax item that has been recognized.
- */
+// The attributes of the syntax item that has been recognized.
static int current_attr = 0; // attr of current syntax word
static int current_id = 0; // ID of current char for syn_get_id()
static int current_trans_id = 0; // idem, transparency removed
@@ -204,23 +194,19 @@ static int current_flags = 0;
static int current_seqnr = 0;
static int current_sub_char = 0;
-/*
- * Methods of combining two clusters
- */
+// Methods of combining two clusters
#define CLUSTER_REPLACE 1 // replace first list with second
#define CLUSTER_ADD 2 // add second list to first
#define CLUSTER_SUBTRACT 3 // subtract second list from first
#define SYN_CLSTR(buf) ((syn_cluster_T *)((buf)->b_syn_clusters.ga_data))
-/*
- * Syntax group IDs have different types:
- * 0 - 19999 normal syntax groups
- * 20000 - 20999 ALLBUT indicator (current_syn_inc_tag added)
- * 21000 - 21999 TOP indicator (current_syn_inc_tag added)
- * 22000 - 22999 CONTAINED indicator (current_syn_inc_tag added)
- * 23000 - 32767 cluster IDs (subtract SYNID_CLUSTER for the cluster ID)
- */
+// Syntax group IDs have different types:
+// 0 - 19999 normal syntax groups
+// 20000 - 20999 ALLBUT indicator (current_syn_inc_tag added)
+// 21000 - 21999 TOP indicator (current_syn_inc_tag added)
+// 22000 - 22999 CONTAINED indicator (current_syn_inc_tag added)
+// 23000 - 32767 cluster IDs (subtract SYNID_CLUSTER for the cluster ID)
#define SYNID_ALLBUT MAX_HL_ID // syntax group ID for contains=ALLBUT
#define SYNID_TOP 21000 // syntax group ID for contains=TOP
#define SYNID_CONTAINED 22000 // syntax group ID for contains=CONTAINED
@@ -234,21 +220,17 @@ static int current_sub_char = 0;
// instead of passing it to them, we stow it here.
static char **syn_cmdlinep;
-/*
- * Another Annoying Hack(TM): To prevent rules from other ":syn include"'d
- * files from leaking into ALLBUT lists, we assign a unique ID to the
- * rules in each ":syn include"'d file.
- */
+// Another Annoying Hack(TM): To prevent rules from other ":syn include"'d
+// files from leaking into ALLBUT lists, we assign a unique ID to the
+// rules in each ":syn include"'d file.
static int current_syn_inc_tag = 0;
static int running_syn_inc_tag = 0;
-/*
- * In a hashtable item "hi_key" points to "keyword" in a keyentry.
- * This avoids adding a pointer to the hashtable item.
- * KE2HIKEY() converts a var pointer to a hashitem key pointer.
- * HIKEY2KE() converts a hashitem key pointer to a var pointer.
- * HI2KE() converts a hashitem pointer to a var pointer.
- */
+// In a hashtable item "hi_key" points to "keyword" in a keyentry.
+// This avoids adding a pointer to the hashtable item.
+// KE2HIKEY() converts a var pointer to a hashitem key pointer.
+// HIKEY2KE() converts a hashitem key pointer to a var pointer.
+// HI2KE() converts a hashitem pointer to a var pointer.
static keyentry_T dumkey;
#define KE2HIKEY(kp) ((kp)->keyword)
#define HIKEY2KE(p) ((keyentry_T *)((p) - (dumkey.keyword - (char_u *)&dumkey)))
@@ -256,11 +238,9 @@ static keyentry_T dumkey;
// -V:HI2KE:782
-/*
- * To reduce the time spent in keepend(), remember at which level in the state
- * stack the first item with "keepend" is present. When "-1", there is no
- * "keepend" on the stack.
- */
+// To reduce the time spent in keepend(), remember at which level in the state
+// stack the first item with "keepend" is present. When "-1", there is no
+// "keepend" on the stack.
static int keepend_level = -1;
static char msg_no_items[] = N_("No Syntax items defined for this buffer");
@@ -272,13 +252,11 @@ static char msg_no_items[] = N_("No Syntax items defined for this buffer");
static int next_seqnr = 1; // value to use for si_seqnr
-/*
- * The next possible match in the current line for any pattern is remembered,
- * to avoid having to try for a match in each column.
- * If next_match_idx == -1, not tried (in this line) yet.
- * If next_match_col == MAXCOL, no match found in this line.
- * (All end positions have the column of the char after the end)
- */
+// The next possible match in the current line for any pattern is remembered,
+// to avoid having to try for a match in each column.
+// If next_match_idx == -1, not tried (in this line) yet.
+// If next_match_col == MAXCOL, no match found in this line.
+// (All end positions have the column of the char after the end)
static int next_match_col; // column for start of next match
static lpos_T next_match_m_endpos; // position for end of next match
static lpos_T next_match_h_startpos; // pos. for highl. start of next match
@@ -290,17 +268,13 @@ static lpos_T next_match_eoe_pos; // pos. for end of end pattern
static int next_match_end_idx; // ID of group for end pattn or zero
static reg_extmatch_T *next_match_extmatch = NULL;
-/*
- * A state stack is an array of integers or stateitem_T, stored in a
- * garray_T. A state stack is invalid if its itemsize entry is zero.
- */
+// A state stack is an array of integers or stateitem_T, stored in a
+// garray_T. A state stack is invalid if its itemsize entry is zero.
#define INVALID_STATE(ssp) ((ssp)->ga_itemsize == 0)
#define VALID_STATE(ssp) ((ssp)->ga_itemsize != 0)
-/*
- * The current state (within the line) of the recognition engine.
- * When current_state.ga_itemsize is 0 the current state is invalid.
- */
+// The current state (within the line) of the recognition engine.
+// When current_state.ga_itemsize is 0 the current state is invalid.
static win_T *syn_win; // current window for highlighting
static buf_T *syn_buf; // current buffer for highlighting
static synblock_T *syn_block; // current buffer for highlighting
@@ -328,13 +302,11 @@ void syn_set_timeout(proftime_T *tm)
syn_tm = tm;
}
-/*
- * Start the syntax recognition for a line. This function is normally called
- * from the screen updating, once for each displayed line.
- * The buffer is remembered in syn_buf, because get_syntax_attr() doesn't get
- * it. Careful: curbuf and curwin are likely to point to another buffer and
- * window.
- */
+// Start the syntax recognition for a line. This function is normally called
+// from the screen updating, once for each displayed line.
+// The buffer is remembered in syn_buf, because get_syntax_attr() doesn't get
+// it. Careful: curbuf and curwin are likely to point to another buffer and
+// window.
void syntax_start(win_T *wp, linenr_T lnum)
{
synstate_T *p;
@@ -348,11 +320,9 @@ void syntax_start(win_T *wp, linenr_T lnum)
current_sub_char = NUL;
- /*
- * After switching buffers, invalidate current_state.
- * Also do this when a change was made, the current state may be invalid
- * then.
- */
+ // After switching buffers, invalidate current_state.
+ // Also do this when a change was made, the current state may be invalid
+ // then.
if (syn_block != wp->w_s
|| syn_buf != wp->w_buffer
|| changedtick != buf_get_changedtick(syn_buf)) {
@@ -363,18 +333,14 @@ void syntax_start(win_T *wp, linenr_T lnum)
changedtick = buf_get_changedtick(syn_buf);
syn_win = wp;
- /*
- * Allocate syntax stack when needed.
- */
+ // Allocate syntax stack when needed.
syn_stack_alloc();
if (syn_block->b_sst_array == NULL) {
return; // out of memory
}
syn_block->b_sst_lasttick = display_tick;
- /*
- * If the state of the end of the previous line is useful, store it.
- */
+ // If the state of the end of the previous line is useful, store it.
if (VALID_STATE(&current_state)
&& current_lnum < lnum
&& current_lnum < syn_buf->b_ml.ml_line_count) {
@@ -384,11 +350,9 @@ void syntax_start(win_T *wp, linenr_T lnum)
(void)store_current_state();
}
- /*
- * If the current_lnum is now the same as "lnum", keep the current
- * state (this happens very often!). Otherwise invalidate
- * current_state and figure it out below.
- */
+ // If the current_lnum is now the same as "lnum", keep the current
+ // state (this happens very often!). Otherwise invalidate
+ // current_state and figure it out below.
if (current_lnum != lnum) {
invalidate_current_state();
}
@@ -396,10 +360,8 @@ void syntax_start(win_T *wp, linenr_T lnum)
invalidate_current_state();
}
- /*
- * Try to synchronize from a saved state in b_sst_array[].
- * Only do this if lnum is not before and not to far beyond a saved state.
- */
+ // Try to synchronize from a saved state in b_sst_array[].
+ // Only do this if lnum is not before and not to far beyond a saved state.
if (INVALID_STATE(&current_state) && syn_block->b_sst_array != NULL) {
// Find last valid saved state before start_lnum.
for (p = syn_block->b_sst_first; p != NULL; p = p->sst_next) {
@@ -418,10 +380,8 @@ void syntax_start(win_T *wp, linenr_T lnum)
}
}
- /*
- * If "lnum" is before or far beyond a line with a saved state, need to
- * re-synchronize.
- */
+ // If "lnum" is before or far beyond a line with a saved state, need to
+ // re-synchronize.
if (INVALID_STATE(&current_state)) {
syn_sync(wp, lnum, last_valid);
if (current_lnum == 1) {
@@ -436,10 +396,8 @@ void syntax_start(win_T *wp, linenr_T lnum)
first_stored = current_lnum;
}
- /*
- * Advance from the sync point or saved state until the current line.
- * Save some entries for syncing with later on.
- */
+ // Advance from the sync point or saved state until the current line.
+ // Save some entries for syncing with later on.
if (syn_block->b_sst_len <= Rows) {
dist = 999999;
} else {
@@ -506,10 +464,8 @@ void syntax_start(win_T *wp, linenr_T lnum)
syn_start_line();
}
-/*
- * We cannot simply discard growarrays full of state_items or buf_states; we
- * have to manually release their extmatch pointers first.
- */
+// We cannot simply discard growarrays full of state_items or buf_states; we
+// have to manually release their extmatch pointers first.
static void clear_syn_state(synstate_T *p)
{
if (p->sst_stacksize > SST_FIX_STATES) {
@@ -522,24 +478,20 @@ static void clear_syn_state(synstate_T *p)
}
}
-/*
- * Cleanup the current_state stack.
- */
+// Cleanup the current_state stack.
static void clear_current_state(void)
{
#define UNREF_STATEITEM_EXTMATCH(si) unref_extmatch((si)->si_extmatch)
GA_DEEP_CLEAR(&current_state, stateitem_T, UNREF_STATEITEM_EXTMATCH);
}
-/*
- * Try to find a synchronisation point for line "lnum".
- *
- * This sets current_lnum and the current state. One of three methods is
- * used:
- * 1. Search backwards for the end of a C-comment.
- * 2. Search backwards for given sync patterns.
- * 3. Simply start on a given number of lines above "lnum".
- */
+// Try to find a synchronisation point for line "lnum".
+//
+// This sets current_lnum and the current state. One of three methods is
+// used:
+// 1. Search backwards for the end of a C-comment.
+// 2. Search backwards for given sync patterns.
+// 3. Simply start on a given number of lines above "lnum".
static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
{
buf_T *curbuf_save;
@@ -560,19 +512,15 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
lpos_T found_m_endpos;
colnr_T prev_current_col;
- /*
- * Clear any current state that might be hanging around.
- */
+ // Clear any current state that might be hanging around.
invalidate_current_state();
- /*
- * Start at least "minlines" back. Default starting point for parsing is
- * there.
- * Start further back, to avoid that scrolling backwards will result in
- * resyncing for every line. Now it resyncs only one out of N lines,
- * where N is minlines * 1.5, or minlines * 2 if minlines is small.
- * Watch out for overflow when minlines is MAXLNUM.
- */
+ // Start at least "minlines" back. Default starting point for parsing is
+ // there.
+ // Start further back, to avoid that scrolling backwards will result in
+ // resyncing for every line. Now it resyncs only one out of N lines,
+ // where N is minlines * 1.5, or minlines * 2 if minlines is small.
+ // Watch out for overflow when minlines is MAXLNUM.
if (syn_block->b_syn_sync_minlines > start_lnum) {
start_lnum = 1;
} else {
@@ -595,9 +543,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
}
current_lnum = start_lnum;
- /*
- * 1. Search backwards for the end of a C-style comment.
- */
+ // 1. Search backwards for the end of a C-style comment.
if (syn_block->b_syn_sync_flags & SF_CCOMMENT) {
// Need to make syn_buf the current buffer for a moment, to be able to
// use find_start_comment().
@@ -606,11 +552,9 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
curbuf_save = curbuf;
curbuf = syn_buf;
- /*
- * Skip lines that end in a backslash.
- */
- for (; start_lnum > 1; --start_lnum) {
- line = ml_get(start_lnum - 1);
+ // Skip lines that end in a backslash.
+ for (; start_lnum > 1; start_lnum--) {
+ line = (char_u *)ml_get(start_lnum - 1);
if (*line == NUL || *(line + STRLEN(line) - 1) != '\\') {
break;
}
@@ -622,11 +566,9 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
wp->w_cursor.lnum = start_lnum;
wp->w_cursor.col = 0;
- /*
- * If the line is inside a comment, need to find the syntax item that
- * defines the comment.
- * Restrict the search for the end of a comment to b_syn_sync_maxlines.
- */
+ // If the line is inside a comment, need to find the syntax item that
+ // defines the comment.
+ // Restrict the search for the end of a comment to b_syn_sync_maxlines.
if (find_start_comment((int)syn_block->b_syn_sync_maxlines) != NULL) {
for (idx = syn_block->b_syn_patterns.ga_len; --idx >= 0;) {
if (SYN_ITEMS(syn_block)[idx].sp_syn.id
@@ -644,11 +586,8 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
wp->w_cursor = cursor_save;
curwin = curwin_save;
curbuf = curbuf_save;
- }
- /*
- * 2. Search backwards for given sync patterns.
- */
- else if (syn_block->b_syn_sync_flags & SF_MATCH) {
+ } else if (syn_block->b_syn_sync_flags & SF_MATCH) {
+ // 2. Search backwards for given sync patterns.
if (syn_block->b_syn_sync_maxlines != 0
&& start_lnum > syn_block->b_syn_sync_maxlines) {
break_lnum = start_lnum - syn_block->b_syn_sync_maxlines;
@@ -675,19 +614,15 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
break;
}
- /*
- * Check if the previous line has the line-continuation pattern.
- */
+ // Check if the previous line has the line-continuation pattern.
if (lnum > 1 && syn_match_linecont(lnum - 1)) {
continue;
}
- /*
- * Start with nothing on the state stack
- */
+ // Start with nothing on the state stack
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);
@@ -712,10 +647,8 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
found_current_lnum = current_lnum;
found_current_col = current_col;
found_m_endpos = cur_si->si_m_endpos;
- /*
- * Continue after the match (be aware of a zero-length
- * match).
- */
+ // Continue after the match (be aware of a zero-length
+ // match).
if (found_m_endpos.lnum > current_lnum) {
current_lnum = found_m_endpos.lnum;
current_col = found_m_endpos.col;
@@ -743,27 +676,21 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
}
}
- /*
- * If a sync point was encountered, break here.
- */
+ // If a sync point was encountered, break here.
if (found_flags) {
- /*
- * Put the item that was specified by the sync point on the
- * state stack. If there was no item specified, make the
- * state stack empty.
- */
+ // Put the item that was specified by the sync point on the
+ // state stack. If there was no item specified, make the
+ // state stack empty.
clear_current_state();
if (found_match_idx >= 0) {
push_current_state(found_match_idx);
update_si_attr(current_state.ga_len - 1);
}
- /*
- * When using "grouphere", continue from the sync point
- * match, until the end of the line. Parsing starts at
- * the next line.
- * For "groupthere" the parsing starts at start_lnum.
- */
+ // When using "grouphere", continue from the sync point
+ // match, until the end of the line. Parsing starts at
+ // the next line.
+ // For "groupthere" the parsing starts at start_lnum.
if (found_flags & HL_SYNC_HERE) {
if (!GA_EMPTY(&current_state)) {
cur_si = &CUR_STATE(current_state.ga_len - 1);
@@ -797,7 +724,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
validate_current_state();
}
-static void save_chartab(char_u *chartab)
+static void save_chartab(char *chartab)
{
if (syn_block->b_syn_isk != empty_option) {
memmove(chartab, syn_buf->b_chartab, (size_t)32);
@@ -805,23 +732,21 @@ static void save_chartab(char_u *chartab)
}
}
-static void restore_chartab(char_u *chartab)
+static void restore_chartab(char *chartab)
{
if (syn_win->w_s->b_syn_isk != empty_option) {
memmove(syn_buf->b_chartab, chartab, (size_t)32);
}
}
-/*
- * 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) {
regmmatch_T regmatch;
// chartab array for syn iskeyword
char_u buf_chartab[32];
- save_chartab(buf_chartab);
+ save_chartab((char *)buf_chartab);
regmatch.rmm_ic = syn_block->b_syn_linecont_ic;
regmatch.regprog = syn_block->b_syn_linecont_prog;
@@ -829,24 +754,20 @@ static int syn_match_linecont(linenr_T lnum)
IF_SYN_TIME(&syn_block->b_syn_linecont_time));
syn_block->b_syn_linecont_prog = regmatch.regprog;
- restore_chartab(buf_chartab);
+ restore_chartab((char *)buf_chartab);
return r;
}
- return FALSE;
+ return false;
}
-/*
- * Prepare the current state for the start of a line.
- */
+// Prepare the current state for the start of a line.
static void syn_start_line(void)
{
current_finished = false;
current_col = 0;
- /*
- * Need to update the end of a start/skip/end that continues from the
- * previous line and regions that have "keepend".
- */
+ // Need to update the end of a start/skip/end that continues from the
+ // previous line and regions that have "keepend".
if (!GA_EMPTY(&current_state)) {
syn_update_ends(true);
check_state_ends();
@@ -878,23 +799,21 @@ 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;
}
}
}
- /*
- * Need to update the end of a start/skip/end that continues from the
- * previous line. And regions that have "keepend", because they may
- * influence contained items. If we've just removed "extend"
- * (startofline == 0) then we should update ends of normal regions
- * contained inside "keepend" because "extend" could have extended
- * these "keepend" regions as well as contained normal regions.
- * Then check for items ending in column 0.
- */
+ // Need to update the end of a start/skip/end that continues from the
+ // previous line. And regions that have "keepend", because they may
+ // influence contained items. If we've just removed "extend"
+ // (startofline == 0) then we should update ends of normal regions
+ // contained inside "keepend" because "extend" could have extended
+ // these "keepend" regions as well as contained normal regions.
+ // Then check for items ending in column 0.
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;
}
@@ -925,37 +844,35 @@ static void syn_update_ends(bool startofline)
/////////////////////////////////////////
// Handling of the state stack cache.
-/*
- * EXPLANATION OF THE SYNTAX STATE STACK CACHE
- *
- * To speed up syntax highlighting, the state stack for the start of some
- * lines is cached. These entries can be used to start parsing at that point.
- *
- * The stack is kept in b_sst_array[] for each buffer. There is a list of
- * valid entries. b_sst_first points to the first one, then follow sst_next.
- * The entries are sorted on line number. The first entry is often for line 2
- * (line 1 always starts with an empty stack).
- * There is also a list for free entries. This construction is used to avoid
- * having to allocate and free memory blocks too often.
- *
- * When making changes to the buffer, this is logged in b_mod_*. When calling
- * update_screen() to update the display, it will call
- * syn_stack_apply_changes() for each displayed buffer to adjust the cached
- * entries. The entries which are inside the changed area are removed,
- * because they must be recomputed. Entries below the changed have their line
- * number adjusted for deleted/inserted lines, and have their sst_change_lnum
- * set to indicate that a check must be made if the changed lines would change
- * the cached entry.
- *
- * When later displaying lines, an entry is stored for each line. Displayed
- * lines are likely to be displayed again, in which case the state at the
- * start of the line is needed.
- * For not displayed lines, an entry is stored for every so many lines. These
- * entries will be used e.g., when scrolling backwards. The distance between
- * entries depends on the number of lines in the buffer. For small buffers
- * the distance is fixed at SST_DIST, for large buffers there is a fixed
- * number of entries SST_MAX_ENTRIES, and the distance is computed.
- */
+// EXPLANATION OF THE SYNTAX STATE STACK CACHE
+//
+// To speed up syntax highlighting, the state stack for the start of some
+// lines is cached. These entries can be used to start parsing at that point.
+//
+// The stack is kept in b_sst_array[] for each buffer. There is a list of
+// valid entries. b_sst_first points to the first one, then follow sst_next.
+// The entries are sorted on line number. The first entry is often for line 2
+// (line 1 always starts with an empty stack).
+// There is also a list for free entries. This construction is used to avoid
+// having to allocate and free memory blocks too often.
+//
+// When making changes to the buffer, this is logged in b_mod_*. When calling
+// update_screen() to update the display, it will call
+// syn_stack_apply_changes() for each displayed buffer to adjust the cached
+// entries. The entries which are inside the changed area are removed,
+// because they must be recomputed. Entries below the changed have their line
+// number adjusted for deleted/inserted lines, and have their sst_change_lnum
+// set to indicate that a check must be made if the changed lines would change
+// the cached entry.
+//
+// When later displaying lines, an entry is stored for each line. Displayed
+// lines are likely to be displayed again, in which case the state at the
+// start of the line is needed.
+// For not displayed lines, an entry is stored for every so many lines. These
+// entries will be used e.g., when scrolling backwards. The distance between
+// entries depends on the number of lines in the buffer. For small buffers
+// the distance is fixed at SST_DIST, for large buffers there is a fixed
+// number of entries SST_MAX_ENTRIES, and the distance is computed.
static void syn_stack_free_block(synblock_T *block)
{
@@ -970,10 +887,8 @@ static void syn_stack_free_block(synblock_T *block)
block->b_sst_len = 0;
}
}
-/*
- * Free b_sst_array[] for buffer "buf".
- * Used when syntax items changed to force resyncing everywhere.
- */
+// Free b_sst_array[] for buffer "buf".
+// Used when syntax items changed to force resyncing everywhere.
void syn_stack_free_all(synblock_T *block)
{
syn_stack_free_block(block);
@@ -986,12 +901,10 @@ void syn_stack_free_all(synblock_T *block)
}
}
-/*
- * Allocate the syntax state stack for syn_buf when needed.
- * If the number of entries in b_sst_array[] is much too big or a bit too
- * small, reallocate it.
- * Also used to allocate b_sst_array[] for the first time.
- */
+// Allocate the syntax state stack for syn_buf when needed.
+// If the number of entries in b_sst_array[] is much too big or a bit too
+// small, reallocate it.
+// Also used to allocate b_sst_array[] for the first time.
static void syn_stack_alloc(void)
{
synstate_T *to, *from;
@@ -1058,12 +971,10 @@ static void syn_stack_alloc(void)
}
}
-/*
- * Check for changes in a buffer to affect stored syntax states. Uses the
- * b_mod_* fields.
- * Called from update_screen(), before screen is being updated, once for each
- * displayed buffer.
- */
+// Check for changes in a buffer to affect stored syntax states. Uses the
+// b_mod_* fields.
+// Called from update_screen(), before screen is being updated, once for each
+// displayed buffer.
void syn_stack_apply_changes(buf_T *buf)
{
syn_stack_apply_changes_block(&buf->b_s, buf);
@@ -1139,11 +1050,9 @@ static bool syn_stack_cleanup(void)
dist = syn_buf->b_ml.ml_line_count / (syn_block->b_sst_len - Rows) + 1;
}
- /*
- * Go through the list to find the "tick" for the oldest entry that can
- * be removed. Set "above" when the "tick" for the oldest entry is above
- * "b_sst_lasttick" (the display tick wraps around).
- */
+ // Go through the list to find the "tick" for the oldest entry that can
+ // be removed. Set "above" when the "tick" for the oldest entry is above
+ // "b_sst_lasttick" (the display tick wraps around).
tick = syn_block->b_sst_lasttick;
bool above = false;
prev = syn_block->b_sst_first;
@@ -1160,10 +1069,8 @@ static bool syn_stack_cleanup(void)
}
}
- /*
- * Go through the list to make the entries for the oldest tick at an
- * interval of several lines.
- */
+ // Go through the list to make the entries for the oldest tick at an
+ // interval of several lines.
prev = syn_block->b_sst_first;
for (p = prev->sst_next; p != NULL; prev = p, p = p->sst_next) {
if (p->sst_tick == tick && prev->sst_lnum + dist > p->sst_lnum) {
@@ -1177,22 +1084,18 @@ static bool syn_stack_cleanup(void)
return retval;
}
-/*
- * Free the allocated memory for a syn_state item.
- * Move the entry into the free list.
- */
+// Free the allocated memory for a syn_state item.
+// Move the entry into the free list.
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++;
}
-/*
- * Find an entry in the list of state stacks at or before "lnum".
- * Returns NULL when there is no entry or the first entry is after "lnum".
- */
+// Find an entry in the list of state stacks at or before "lnum".
+// Returns NULL when there is no entry or the first entry is after "lnum".
static synstate_T *syn_stack_find_entry(linenr_T lnum)
{
synstate_T *p, *prev;
@@ -1209,10 +1112,8 @@ static synstate_T *syn_stack_find_entry(linenr_T lnum)
return prev;
}
-/*
- * Try saving the current state in b_sst_array[].
- * The current state must be valid for the start of the current_lnum line!
- */
+// Try saving the current state in b_sst_array[].
+// The current state must be valid for the start of the current_lnum line!
static synstate_T *store_current_state(void)
{
int i;
@@ -1221,11 +1122,9 @@ static synstate_T *store_current_state(void)
stateitem_T *cur_si;
synstate_T *sp = syn_stack_find_entry(current_lnum);
- /*
- * 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) {
+ // 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--) {
cur_si = &CUR_STATE(i);
if (cur_si->si_h_startpos.lnum >= current_lnum
|| cur_si->si_m_endpos.lnum >= current_lnum
@@ -1256,9 +1155,7 @@ static synstate_T *store_current_state(void)
sp = NULL;
}
} else if (sp == NULL || sp->sst_lnum != current_lnum) {
- /*
- * Add a new entry
- */
+ // Add a new entry
// If no free items, cleanup the array first.
if (syn_block->b_sst_freecount == 0) {
(void)syn_stack_cleanup();
@@ -1273,7 +1170,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 +1199,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;
@@ -1318,9 +1215,7 @@ static synstate_T *store_current_state(void)
return sp;
}
-/*
- * Copy a state stack from "from" in b_sst_array[] to current_state;
- */
+// Copy a state stack from "from" in b_sst_array[] to current_state;
static void load_current_state(synstate_T *from)
{
int i;
@@ -1336,7 +1231,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 +1240,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 =
@@ -1424,16 +1319,14 @@ static bool syn_stack_equal(synstate_T *sp)
return i < 0 ? true : false;
}
-/*
- * We stop parsing syntax above line "lnum". If the stored state at or below
- * this line depended on a change before it, it now depends on the line below
- * the last parsed line.
- * The window looks like this:
- * line which changed
- * displayed line
- * displayed line
- * lnum -> line below window
- */
+// We stop parsing syntax above line "lnum". If the stored state at or below
+// this line depended on a change before it, it now depends on the line below
+// the last parsed line.
+// The window looks like this:
+// line which changed
+// displayed line
+// displayed line
+// lnum -> line below window
void syntax_end_parsing(linenr_T lnum)
{
synstate_T *sp;
@@ -1448,9 +1341,8 @@ void syntax_end_parsing(linenr_T lnum)
}
}
-/*
- * End of handling of the state stack.
- ****************************************/
+// End of handling of the state stack.
+// **************************************
static void invalidate_current_state(void)
{
@@ -1475,33 +1367,25 @@ bool syntax_check_changed(linenr_T lnum)
bool retval = true;
synstate_T *sp;
- /*
- * Check the state stack when:
- * - lnum is just below the previously syntaxed line.
- * - lnum is not before the lines with saved states.
- * - lnum is not past the lines with saved states.
- * - lnum is at or before the last changed line.
- */
+ // Check the state stack when:
+ // - lnum is just below the previously syntaxed line.
+ // - lnum is not before the lines with saved states.
+ // - lnum is not past the lines with saved states.
+ // - lnum is at or before the last changed line.
if (VALID_STATE(&current_state) && lnum == current_lnum + 1) {
sp = syn_stack_find_entry(lnum);
if (sp != NULL && sp->sst_lnum == lnum) {
- /*
- * finish the previous line (needed when not all of the line was
- * drawn)
- */
+ // finish the previous line (needed when not all of the line was
+ // drawn)
(void)syn_finish_line(false);
- /*
- * Compare the current state with the previously saved state of
- * the line.
- */
+ // Compare the current state with the previously saved state of
+ // the line.
if (syn_stack_equal(sp)) {
retval = false;
}
- /*
- * Store the current state in b_sst_array[] for later use.
- */
+ // Store the current state in b_sst_array[] for later use.
current_lnum++;
(void)store_current_state();
}
@@ -1551,7 +1435,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"
@@ -1589,9 +1473,7 @@ int get_syntax_attr(const colnr_T col, bool *const can_spell, const bool keep_st
validate_current_state();
}
- /*
- * Skip from the current column to "col", get the attributes for "col".
- */
+ // Skip from the current column to "col", get the attributes for "col".
while (current_col <= col) {
attr = syn_current_attr(false, true, can_spell,
current_col == col ? keep_state : false);
@@ -1636,15 +1518,11 @@ 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.
- */
+ // If we found a match after the last column, use it.
if (next_match_idx >= 0 && next_match_col >= (int)current_col
&& next_match_col != MAXCOL) {
(void)push_next_match();
@@ -1661,11 +1539,9 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
current_state_stored = false;
}
- /*
- * When in the previous column there was a match but it could not be used
- * (empty match or already matched in this column) need to try again in
- * the next column.
- */
+ // When in the previous column there was a match but it could not be used
+ // (empty match or already matched in this column) need to try again in
+ // the next column.
if (try_next_column) {
next_match_idx = -1;
try_next_column = false;
@@ -1681,25 +1557,21 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
ga_init(&zero_width_next_ga, (int)sizeof(int), 10);
// use syntax iskeyword option
- save_chartab(buf_chartab);
+ save_chartab((char *)buf_chartab);
- /*
- * Repeat matching keywords and patterns, to find contained items at the
- * same column. This stops when there are no extra matches at the current
- * column.
- */
+ // Repeat matching keywords and patterns, to find contained items at the
+ // same column. This stops when there are no extra matches at the current
+ // column.
do {
found_match = false;
keep_next_list = false;
int syn_id = 0;
- /*
- * 1. Check for a current state.
- * Only when there is no current state, or if the current state may
- * contain other things, we need to check for keywords and patterns.
- * Always need to check for contained items if some item has the
- * "containedin" argument (takes extra time!).
- */
+ // 1. Check for a current state.
+ // Only when there is no current state, or if the current state may
+ // contain other things, we need to check for keywords and patterns.
+ // Always need to check for contained items if some item has the
+ // "containedin" argument (takes extra time!).
if (current_state.ga_len) {
cur_si = &CUR_STATE(current_state.ga_len - 1);
} else {
@@ -1708,18 +1580,17 @@ 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)
+ if (vim_iswordp_buf((char *)cur_pos, syn_buf)
&& (current_col == 0
- || !vim_iswordp_buf(cur_pos - 1 - utf_head_off(line, cur_pos - 1),
+ || !vim_iswordp_buf((char *)cur_pos - 1 -
+ utf_head_off((char *)line, (char *)cur_pos - 1),
syn_buf))) {
- syn_id = check_keyword_id(line, (int)current_col, &endcol, &flags,
+ syn_id = check_keyword_id((char *)line, (int)current_col, &endcol, &flags,
&next_list, cur_si, &cchar);
if (syn_id != 0) {
push_current_state(KEYWORD_IDX);
@@ -1732,7 +1603,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++;
@@ -1763,21 +1634,15 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
}
}
- /*
- * 3. Check for patterns (only if no keyword found).
- */
+ // 3. Check for patterns (only if no keyword found).
if (syn_id == 0 && syn_block->b_syn_patterns.ga_len) {
- /*
- * If we didn't check for a match yet, or we are past it, check
- * for any match with a pattern.
- */
+ // If we didn't check for a match yet, or we are past it, check
+ // for any match with a pattern.
if (next_match_idx < 0 || next_match_col < (int)current_col) {
- /*
- * Check all relevant patterns for a match at this
- * position. This is complicated, because matching with a
- * pattern takes quite a bit of time, thus we want to
- * avoid doing it when it's not needed.
- */
+ // Check all relevant patterns for a match at this
+ // position. This is complicated, because matching with a
+ // pattern takes quite a bit of time, thus we want to
+ // avoid doing it when it's not needed.
next_match_idx = 0; // no match in this line yet
next_match_col = MAXCOL;
for (int idx = syn_block->b_syn_patterns.ga_len; --idx >= 0;) {
@@ -1819,9 +1684,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
continue;
}
- /*
- * Compute the first column of the match.
- */
+ // Compute the first column of the match.
syn_add_start_off(&pos, &regmatch,
spp, SPO_MS_OFF, -1);
if (pos.lnum > current_lnum) {
@@ -1836,19 +1699,15 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
// matches in the current line
spp->sp_startcol = startcol;
- /*
- * If a previously found match starts at a lower
- * column number, don't use this one.
- */
+ // If a previously found match starts at a lower
+ // column number, don't use this one.
if (startcol >= next_match_col) {
continue;
}
- /*
- * If we matched this pattern at this position
- * before, skip it. Must retry in the next
- * column, because it may match from there.
- */
+ // If we matched this pattern at this position
+ // before, skip it. Must retry in the next
+ // column, because it may match from there.
if (did_match_already(idx, &zero_width_next_ga)) {
try_next_column = true;
continue;
@@ -1866,10 +1725,8 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
syn_add_end_off(&eos_pos, &regmatch,
spp, SPO_RS_OFF, 0);
- /*
- * Grab the external submatches before they get
- * overwritten. Reference count doesn't change.
- */
+ // Grab the external submatches before they get
+ // overwritten. Reference count doesn't change.
unref_extmatch(cur_extmatch);
cur_extmatch = re_extmatch_out;
re_extmatch_out = NULL;
@@ -1880,12 +1737,10 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
end_idx = 0;
hl_endpos.lnum = 0;
- /*
- * For a "oneline" the end must be found in the
- * same line too. Search for it after the end of
- * the match with the start pattern. Set the
- * resulting end positions at the same time.
- */
+ // For a "oneline" the end must be found in the
+ // same line too. Search for it after the end of
+ // the match with the start pattern. Set the
+ // resulting end positions at the same time.
if (spp->sp_type == SPTYPE_START
&& (spp->sp_flags & HL_ONELINE)) {
lpos_T startpos;
@@ -1896,23 +1751,18 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
if (endpos.lnum == 0) {
continue; // not found
}
- }
- /*
- * For a "match" the size must be > 0 after the
- * end offset needs has been added. Except when
- * syncing.
- */
- else if (spp->sp_type == SPTYPE_MATCH) {
+ } else if (spp->sp_type == SPTYPE_MATCH) {
+ // For a "match" the size must be > 0 after the
+ // end offset needs has been added. Except when
+ // syncing.
syn_add_end_off(&hl_endpos, &regmatch, spp,
SPO_HE_OFF, 0);
syn_add_end_off(&endpos, &regmatch, spp,
SPO_ME_OFF, 0);
if (endpos.lnum == current_lnum
&& (int)endpos.col + syncing < startcol) {
- /*
- * If an empty string is matched, may need
- * to try matching again at next column.
- */
+ // If an empty string is matched, may need
+ // to try matching again at next column.
if (regmatch.startpos[0].col == regmatch.endpos[0].col) {
try_next_column = true;
}
@@ -1920,9 +1770,8 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
}
}
- /*
- * keep the best match so far in next_match_*
- */
+ // keep the best match so far in next_match_*
+
// Highlighting must start after startpos and end
// before endpos.
if (hl_startpos.lnum == current_lnum
@@ -1947,9 +1796,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
}
}
- /*
- * If we found a match at the current column, use it.
- */
+ // If we found a match at the current column, use it.
if (next_match_idx >= 0 && next_match_col == (int)current_col) {
synpat_T *lspp;
@@ -1977,17 +1824,13 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
}
}
- /*
- * Handle searching for nextgroup match.
- */
+ // 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)
@@ -1996,14 +1839,12 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
}
}
- /*
- * If a nextgroup was found: Use it, and continue looking for
- * contained matches.
- * If a nextgroup was not found: Continue looking for a normal
- * match.
- * When did set current_next_list for a zero-width item and no
- * match was found don't loop (would get stuck).
- */
+ // If a nextgroup was found: Use it, and continue looking for
+ // contained matches.
+ // If a nextgroup was not found: Continue looking for a normal
+ // match.
+ // When did set current_next_list for a zero-width item and no
+ // match was found don't loop (would get stuck).
current_next_list = NULL;
next_match_idx = -1;
if (!zero_width_next_list) {
@@ -2012,19 +1853,17 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
}
} while (found_match);
- restore_chartab(buf_chartab);
+ restore_chartab((char *)buf_chartab);
- /*
- * Use attributes from the current state, if within its highlighting.
- * If not, use attributes from the current-but-one state, etc.
- */
+ // Use attributes from the current state, if within its highlighting.
+ // If not, use attributes from the current-but-one state, etc.
current_attr = 0;
current_id = 0;
current_trans_id = 0;
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 +1885,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.
@@ -2085,14 +1922,12 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
}
}
- /*
- * Check for end of current state (and the states before it) at the
- * next column. Don't do this for syncing, because we would miss a
- * single character match.
- * First check if the current state ends at the current column. It
- * may be for an empty match and a containing item might end in the
- * current column.
- */
+ // Check for end of current state (and the states before it) at the
+ // next column. Don't do this for syncing, because we would miss a
+ // single character match.
+ // First check if the current state ends at the current column. It
+ // may be for an empty match and a containing item might end in the
+ // current column.
if (!syncing && !keep_state) {
check_state_ends();
if (!GA_EMPTY(&current_state)
@@ -2112,7 +1947,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;
@@ -2152,9 +1987,7 @@ static bool did_match_already(int idx, garray_T *gap)
return false;
}
-/*
- * Push the next match onto the stack.
- */
+// Push the next match onto the stack.
static stateitem_T *push_next_match(void)
{
stateitem_T *cur_si;
@@ -2163,15 +1996,11 @@ static stateitem_T *push_next_match(void)
spp = &(SYN_ITEMS(syn_block)[next_match_idx]);
- /*
- * Push the item in current_state stack;
- */
+ // Push the item in current_state stack;
push_current_state(next_match_idx);
{
- /*
- * If it's a start-skip-end type that crosses lines, figure out how
- * much it continues in this line. Otherwise just fill in the length.
- */
+ // If it's a start-skip-end type that crosses lines, figure out how
+ // much it continues in this line. Otherwise just fill in the length.
cur_si = &CUR_STATE(current_state.ga_len - 1);
cur_si->si_h_startpos = next_match_h_startpos;
cur_si->si_m_startcol = current_col;
@@ -2192,7 +2021,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;
@@ -2204,10 +2033,8 @@ static stateitem_T *push_next_match(void)
update_si_attr(current_state.ga_len - 1);
save_flags = cur_si->si_flags & (HL_CONCEAL | HL_CONCEALENDS);
- /*
- * If the start pattern has another highlight group, push another item
- * on the stack for the start pattern.
- */
+ // If the start pattern has another highlight group, push another item
+ // on the stack for the start pattern.
if (spp->sp_type == SPTYPE_START && spp->sp_syn_match_id != 0) {
push_current_state(next_match_idx);
cur_si = &CUR_STATE(current_state.ga_len - 1);
@@ -2216,7 +2043,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++;
@@ -2235,9 +2062,7 @@ static stateitem_T *push_next_match(void)
return cur_si;
}
-/*
- * Check for end of current state (and the states before it).
- */
+// Check for end of current state (and the states before it).
static void check_state_ends(void)
{
stateitem_T *cur_si;
@@ -2249,12 +2074,10 @@ static void check_state_ends(void)
&& (cur_si->si_m_endpos.lnum < current_lnum
|| (cur_si->si_m_endpos.lnum == current_lnum
&& cur_si->si_m_endpos.col <= current_col))) {
- /*
- * If there is an end pattern group ID, highlight the end pattern
- * now. No need to pop the current item from the stack.
- * Only do this if the end pattern continues beyond the current
- * position.
- */
+ // If there is an end pattern group ID, highlight the end pattern
+ // now. No need to pop the current item from the stack.
+ // Only do this if the end pattern continues beyond the current
+ // position.
if (cur_si->si_end_idx
&& (cur_si->si_eoe_pos.lnum > current_lnum
|| (cur_si->si_eoe_pos.lnum == current_lnum
@@ -2331,10 +2154,8 @@ static void check_state_ends(void)
}
}
-/*
- * Update an entry in the current_state stack for a match or region. This
- * fills in si_attr, si_next_list and si_cont_list.
- */
+// Update an entry in the current_state stack for a match or region. This
+// fills in si_attr, si_next_list and si_cont_list.
static void update_si_attr(int idx)
{
stateitem_T *sip = &CUR_STATE(idx);
@@ -2359,11 +2180,9 @@ static void update_si_attr(int idx)
sip->si_cont_list = spp->sp_cont_list;
}
- /*
- * For transparent items, take attr from outer item.
- * Also take cont_list, if there is none.
- * Don't do this for the matchgroup of a start or end pattern.
- */
+ // For transparent items, take attr from outer item.
+ // Also take cont_list, if there is none.
+ // Don't do this for the matchgroup of a start or end pattern.
if ((spp->sp_flags & HL_TRANSP) && !(sip->si_flags & HL_MATCH)) {
if (idx == 0) {
sip->si_attr = 0;
@@ -2382,10 +2201,8 @@ static void update_si_attr(int idx)
}
}
-/*
- * Check the current stack for patterns with "keepend" flag.
- * Propagate the match-end to contained items, until a "skipend" item is found.
- */
+// Check the current stack for patterns with "keepend" flag.
+// Propagate the match-end to contained items, until a "skipend" item is found.
static void check_keepend(void)
{
int i;
@@ -2393,20 +2210,16 @@ static void check_keepend(void)
lpos_T maxpos_h;
stateitem_T *sip;
- /*
- * This check can consume a lot of time; only do it from the level where
- * there really is a keepend.
- */
+ // This check can consume a lot of time; only do it from the level where
+ // there really is a keepend.
if (keepend_level < 0) {
return;
}
- /*
- * Find the last index of an "extend" item. "keepend" items before that
- * 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) {
+ // Find the last index of an "extend" item. "keepend" items before that
+ // 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--) {
if (CUR_STATE(i).si_flags & HL_EXTEND) {
break;
}
@@ -2416,13 +2229,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
@@ -2465,10 +2278,8 @@ static void update_si_end(stateitem_T *sip, int startcol, bool force)
return;
}
- /*
- * We need to find the end of the region. It may continue in the next
- * line.
- */
+ // We need to find the end of the region. It may continue in the next
+ // line.
int end_idx = 0;
lpos_T startpos = {
.lnum = current_lnum,
@@ -2482,12 +2293,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,15 +2307,13 @@ 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;
}
}
-/*
- * Add a new state to the current state stack.
- * It is cleared and the index set to "idx".
- */
+// Add a new state to the current state stack.
+// It is cleared and the index set to "idx".
static void push_current_state(int idx)
{
stateitem_T *p = GA_APPEND_VIA_PTR(stateitem_T, &current_state);
@@ -2512,14 +2321,12 @@ static void push_current_state(int idx)
p->si_idx = idx;
}
-/*
- * Remove a state from the current_state stack.
- */
+// Remove a state from the current_state stack.
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;
@@ -2565,20 +2372,16 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
return;
}
- /*
- * Check for being called with a START pattern.
- * Can happen with a match that continues to the next line, because it
- * contained a region.
- */
+ // Check for being called with a START pattern.
+ // Can happen with a match that continues to the next line, because it
+ // contained a region.
spp = &(SYN_ITEMS(syn_block)[idx]);
if (spp->sp_type != SPTYPE_START) {
*hl_endpos = *startpos;
return;
}
- /*
- * Find the SKIP or first END pattern after the last START pattern.
- */
+ // Find the SKIP or first END pattern after the last START pattern.
for (;;) {
spp = &(SYN_ITEMS(syn_block)[idx]);
if (spp->sp_type != SPTYPE_START) {
@@ -2587,9 +2390,7 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
idx++;
}
- /*
- * Lookup the SKIP pattern (if present)
- */
+ // Lookup the SKIP pattern (if present)
if (spp->sp_type == SPTYPE_SKIP) {
spp_skip = spp;
idx++;
@@ -2606,14 +2407,12 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
best_regmatch.startpos[0].col = 0; // avoid compiler warning
// use syntax iskeyword option
- save_chartab(buf_chartab);
+ save_chartab((char *)buf_chartab);
for (;;) {
- /*
- * Find end pattern that matches first after "matchcol".
- */
+ // 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]);
@@ -2640,18 +2439,14 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
}
}
- /*
- * If all end patterns have been tried, and there is no match, the
- * item continues until end-of-line.
- */
+ // If all end patterns have been tried, and there is no match, the
+ // item continues until end-of-line.
if (best_idx == -1) {
break;
}
- /*
- * If the skip pattern matches before the end pattern,
- * continue searching after the skip pattern.
- */
+ // If the skip pattern matches before the end pattern,
+ // continue searching after the skip pattern.
if (spp_skip != NULL) {
int lc_col = matchcol - spp_skip->sp_offsets[SPO_LC_OFF];
@@ -2673,7 +2468,7 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
break;
}
- line = ml_get_buf(syn_buf, startpos->lnum, false);
+ line = (char_u *)ml_get_buf(syn_buf, startpos->lnum, false);
int line_len = (int)STRLEN(line);
// take care of an empty match or negative offset
@@ -2697,10 +2492,8 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
}
}
- /*
- * Match from start pattern to end pattern.
- * Correct for match and highlight offset of end pattern.
- */
+ // Match from start pattern to end pattern.
+ // Correct for match and highlight offset of end pattern.
spp = &(SYN_ITEMS(syn_block)[best_idx]);
syn_add_end_off(m_endpos, &best_regmatch, spp, SPO_ME_OFF, 1);
// can't end before the start
@@ -2717,9 +2510,7 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
// can't end after the match
limit_pos(end_endpos, m_endpos);
- /*
- * If the end group is highlighted differently, adjust the pointers.
- */
+ // If the end group is highlighted differently, adjust the pointers.
if (spp->sp_syn_match_id != spp->sp_syn.id && spp->sp_syn_match_id != 0) {
*end_idx = best_idx;
if (spp->sp_off_flags & (1 << (SPO_RE_OFF + SPO_COUNT))) {
@@ -2757,16 +2548,14 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
m_endpos->lnum = 0;
}
- restore_chartab(buf_chartab);
+ restore_chartab((char *)buf_chartab);
// Remove external matches.
unref_extmatch(re_extmatch_in);
re_extmatch_in = NULL;
}
-/*
- * Limit "pos" not to be after "limit".
- */
+// Limit "pos" not to be after "limit".
static void limit_pos(lpos_T *pos, lpos_T *limit)
{
if (pos->lnum > limit->lnum) {
@@ -2776,9 +2565,7 @@ static void limit_pos(lpos_T *pos, lpos_T *limit)
}
}
-/*
- * Limit "pos" not to be after "limit", unless pos->lnum is zero.
- */
+// Limit "pos" not to be after "limit", unless pos->lnum is zero.
static void limit_pos_zero(lpos_T *pos, lpos_T *limit)
{
if (pos->lnum == 0) {
@@ -2817,7 +2604,7 @@ static void syn_add_end_off(lpos_T *result, regmmatch_T *regmatch, synpat_T *spp
if (result->lnum > syn_buf->b_ml.ml_line_count) {
col = 0;
} else if (off != 0) {
- base = ml_get_buf(syn_buf, result->lnum, false);
+ base = (char_u *)ml_get_buf(syn_buf, result->lnum, false);
p = base + col;
if (off > 0) {
while (off-- > 0 && *p != NUL) {
@@ -2862,7 +2649,7 @@ static void syn_add_start_off(lpos_T *result, regmmatch_T *regmatch, synpat_T *s
col = (int)STRLEN(ml_get_buf(syn_buf, result->lnum, false));
}
if (off != 0) {
- base = ml_get_buf(syn_buf, result->lnum, false);
+ base = (char_u *)ml_get_buf(syn_buf, result->lnum, false);
p = base + col;
if (off > 0) {
while (off-- && *p != NUL) {
@@ -2878,18 +2665,14 @@ 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);
}
-/*
- * Call vim_regexec() to find a match with "rmp" in "syn_buf".
- * Returns TRUE when there is a match.
- */
+// Call vim_regexec() to find a match with "rmp" in "syn_buf".
+// Returns true when there is a match.
static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T *st)
{
int timed_out = 0;
@@ -2916,9 +2699,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 +2712,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.
@@ -2944,16 +2727,16 @@ static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T
/// @param next_listp return: next_list of matching keyword
/// @param cur_si item at the top of the stack
/// @param ccharp conceal substitution char
-static int check_keyword_id(char_u *const line, const int startcol, int *const endcolp,
+static int check_keyword_id(char *const line, const int startcol, int *const endcolp,
long *const flagsp, int16_t **const next_listp,
stateitem_T *const cur_si, int *const ccharp)
{
// Find first character after the keyword. First character was already
// checked.
- char_u *const kwp = line + startcol;
+ char *const kwp = line + startcol;
int kwlen = 0;
do {
- kwlen += utfc_ptr2len((char *)kwp + kwlen);
+ kwlen += utfc_ptr2len(kwp + kwlen);
} while (vim_iswordp_buf(kwp + kwlen, syn_buf));
if (kwlen > MAXKEYWLEN) {
@@ -2969,13 +2752,13 @@ static int check_keyword_id(char_u *const line, const int startcol, int *const e
// matching case
if (syn_block->b_keywtab.ht_used != 0) {
- kp = match_keyword(keyword, &syn_block->b_keywtab, cur_si);
+ kp = match_keyword((char *)keyword, &syn_block->b_keywtab, cur_si);
}
// ignoring case
if (kp == NULL && syn_block->b_keywtab_ic.ht_used != 0) {
- str_foldcase(kwp, kwlen, keyword, MAXKEYWLEN + 1);
- kp = match_keyword(keyword, &syn_block->b_keywtab_ic, cur_si);
+ str_foldcase((char_u *)kwp, kwlen, keyword, MAXKEYWLEN + 1);
+ kp = match_keyword((char *)keyword, &syn_block->b_keywtab_ic, cur_si);
}
if (kp != NULL) {
@@ -2994,9 +2777,9 @@ static int check_keyword_id(char_u *const line, const int startcol, int *const e
/// When current_next_list is non-zero accept only that group, otherwise:
/// Accept a not-contained keyword at toplevel.
/// Accept a keyword at other levels only if it is in the contains list.
-static keyentry_T *match_keyword(char_u *keyword, hashtab_T *ht, stateitem_T *cur_si)
+static keyentry_T *match_keyword(char *keyword, hashtab_T *ht, stateitem_T *cur_si)
{
- hashitem_T *hi = hash_find(ht, (char *)keyword);
+ hashitem_T *hi = hash_find(ht, keyword);
if (!HASHITEM_EMPTY(hi)) {
for (keyentry_T *kp = HI2KE(hi); kp != NULL; kp = kp->ke_next) {
if (current_next_list != 0
@@ -3012,20 +2795,18 @@ static keyentry_T *match_keyword(char_u *keyword, hashtab_T *ht, stateitem_T *cu
return NULL;
}
-/*
- * Handle ":syntax conceal" command.
- */
+// Handle ":syntax conceal" command.
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");
@@ -3041,15 +2822,13 @@ static void syn_cmd_conceal(exarg_T *eap, int syncing)
}
}
-/*
- * Handle ":syntax case" command.
- */
+/// Handle ":syntax case" command.
static void syn_cmd_case(exarg_T *eap, int syncing)
{
- char_u *arg = (char_u *)eap->arg;
- char_u *next;
+ char *arg = eap->arg;
+ char *next;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd(arg);
if (eap->skip) {
return;
}
@@ -3076,7 +2855,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 +2872,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) {
@@ -3109,15 +2888,13 @@ static void syn_cmd_foldlevel(exarg_T *eap, int syncing)
}
}
-/*
- * Handle ":syntax spell" command.
- */
+/// Handle ":syntax spell" command.
static void syn_cmd_spell(exarg_T *eap, int syncing)
{
- char_u *arg = (char_u *)eap->arg;
- char_u *next;
+ char *arg = eap->arg;
+ char *next;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd(arg);
if (eap->skip) {
return;
}
@@ -3143,26 +2920,26 @@ 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.
static void syn_cmd_iskeyword(exarg_T *eap, int syncing)
{
- char_u *arg = (char_u *)eap->arg;
- char_u save_chartab[32];
- char_u *save_isk;
+ char *arg = eap->arg;
+ char save_chartab[32];
+ char *save_isk;
if (eap->skip) {
return;
}
- arg = (char_u *)skipwhite((char *)arg);
+ arg = skipwhite(arg);
if (*arg == NUL) {
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"));
}
@@ -3173,7 +2950,7 @@ static void syn_cmd_iskeyword(exarg_T *eap, int syncing)
} else {
memmove(save_chartab, curbuf->b_chartab, (size_t)32);
save_isk = curbuf->b_p_isk;
- curbuf->b_p_isk = vim_strsave(arg);
+ curbuf->b_p_isk = xstrdup(arg);
buf_init_chartab(curbuf, false);
memmove(curwin->w_s->b_syn_chartab, curbuf->b_chartab, (size_t)32);
@@ -3183,12 +2960,10 @@ static void syn_cmd_iskeyword(exarg_T *eap, int syncing)
curbuf->b_p_isk = save_isk;
}
}
- redraw_later(curwin, NOT_VALID);
+ redraw_later(curwin, UPD_NOT_VALID);
}
-/*
- * Clear all syntax info for one buffer.
- */
+// Clear all syntax info for one buffer.
void syntax_clear(synblock_T *block)
{
block->b_syn_error = false; // clear previous error
@@ -3236,9 +3011,7 @@ void syntax_clear(synblock_T *block)
running_syn_inc_tag = 0;
}
-/*
- * Get rid of ownsyntax for window "wp".
- */
+// Get rid of ownsyntax for window "wp".
void reset_synblock(win_T *wp)
{
if (wp->w_s != &wp->w_buffer->b_s) {
@@ -3248,9 +3021,7 @@ void reset_synblock(win_T *wp)
}
}
-/*
- * Clear syncing info for one buffer.
- */
+// Clear syncing info for one buffer.
static void syntax_sync_clear(void)
{
// free the syntax patterns
@@ -3273,26 +3044,22 @@ static void syntax_sync_clear(void)
syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
}
-/*
- * Remove one pattern from the buffer's pattern list.
- */
+// Remove one pattern from the buffer's pattern list.
static void syn_remove_pattern(synblock_T *block, int idx)
{
synpat_T *spp;
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));
block->b_syn_patterns.ga_len--;
}
-/*
- * Clear and free one syntax pattern. When clearing all, must be called from
- * last to first!
- */
+// Clear and free one syntax pattern. When clearing all, must be called from
+// last to first!
static void syn_clear_pattern(synblock_T *block, int i)
{
xfree(SYN_ITEMS(block)[i].sp_pattern);
@@ -3305,9 +3072,7 @@ static void syn_clear_pattern(synblock_T *block, int i)
}
}
-/*
- * Clear and free one syntax cluster.
- */
+// Clear and free one syntax cluster.
static void syn_clear_cluster(synblock_T *block, int i)
{
xfree(SYN_CLSTR(block)[i].scl_name);
@@ -3315,34 +3080,28 @@ static void syn_clear_cluster(synblock_T *block, int i)
xfree(SYN_CLSTR(block)[i].scl_list);
}
-/*
- * Handle ":syntax clear" command.
- */
+/// Handle ":syntax clear" command.
static void syn_cmd_clear(exarg_T *eap, int syncing)
{
- char_u *arg = (char_u *)eap->arg;
- char_u *arg_end;
+ char *arg = eap->arg;
+ char *arg_end;
int id;
- eap->nextcmd = (char *)find_nextcmd(arg);
+ eap->nextcmd = find_nextcmd(arg);
if (eap->skip) {
return;
}
- /*
- * We have to disable this within ":syn include @group filename",
- * because otherwise @group would get deleted.
- * Only required for Vim 5.x syntax files, 6.0 ones don't contain ":syn
- * clear".
- */
+ // We have to disable this within ":syn include @group filename",
+ // because otherwise @group would get deleted.
+ // Only required for Vim 5.x syntax files, 6.0 ones don't contain ":syn
+ // clear".
if (curwin->w_s->b_syn_topgrp != 0) {
return;
}
if (ends_excmd(*arg)) {
- /*
- * No argument: Clear all syntax items.
- */
+ // No argument: Clear all syntax items.
if (syncing) {
syntax_sync_clear();
} else {
@@ -3353,9 +3112,7 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
do_unlet(S_LEN("w:current_syntax"), true);
}
} else {
- /*
- * Clear the group IDs that are in the argument.
- */
+ // Clear the group IDs that are in the argument.
while (!ends_excmd(*arg)) {
arg_end = skiptowhite(arg);
if (*arg == '@') {
@@ -3372,7 +3129,7 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
XFREE_CLEAR(SYN_CLSTR(curwin->w_s)[scl_id].scl_list);
}
} else {
- id = syn_name2id_len((char *)arg, (size_t)(arg_end - arg));
+ id = syn_name2id_len(arg, (size_t)(arg_end - arg));
if (id == 0) {
semsg(_(e_nogroup), arg);
break;
@@ -3380,16 +3137,14 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
syn_clear_one(id, syncing);
}
}
- arg = (char_u *)skipwhite((char *)arg_end);
+ arg = skipwhite(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.
}
-/*
- * Clear one syntax group for the current buffer.
- */
+// Clear one syntax group for the current buffer.
static void syn_clear_one(const int id, const bool syncing)
{
synpat_T *spp;
@@ -3410,37 +3165,29 @@ static void syn_clear_one(const int id, const bool syncing)
}
}
-/*
- * Handle ":syntax on" command.
- */
+// Handle ":syntax on" command.
static void syn_cmd_on(exarg_T *eap, int syncing)
{
syn_cmd_onoff(eap, "syntax");
}
-/*
- * Handle ":syntax reset" command.
- * It actually resets highlighting, not syntax.
- */
+// Handle ":syntax reset" command.
+// It actually resets highlighting, not syntax.
static void syn_cmd_reset(exarg_T *eap, int syncing)
{
- eap->nextcmd = (char *)check_nextcmd((char_u *)eap->arg);
+ eap->nextcmd = check_nextcmd(eap->arg);
if (!eap->skip) {
init_highlight(true, true);
}
}
-/*
- * Handle ":syntax manual" command.
- */
+// Handle ":syntax manual" command.
static void syn_cmd_manual(exarg_T *eap, int syncing)
{
syn_cmd_onoff(eap, "manual");
}
-/*
- * Handle ":syntax off" command.
- */
+// Handle ":syntax off" command.
static void syn_cmd_off(exarg_T *eap, int syncing)
{
syn_cmd_onoff(eap, "nosyntax");
@@ -3449,7 +3196,7 @@ static void syn_cmd_off(exarg_T *eap, int syncing)
static void syn_cmd_onoff(exarg_T *eap, char *name)
FUNC_ATTR_NONNULL_ALL
{
- eap->nextcmd = (char *)check_nextcmd((char_u *)eap->arg);
+ eap->nextcmd = check_nextcmd(eap->arg);
if (!eap->skip) {
did_syntax_onoff = true;
char buf[100];
@@ -3471,13 +3218,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;
}
@@ -3520,23 +3267,19 @@ static void syn_cmd_list(exarg_T *eap, int syncing)
msg_puts_title(_("\n--- Syntax items ---"));
}
if (ends_excmd(*arg)) {
- /*
- * No argument: List all group IDs and all syntax clusters.
- */
+ // No argument: List all group IDs and all syntax clusters.
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 {
- /*
- * List the group IDs and syntax clusters that are in the argument.
- */
+ // 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));
+ int id = syn_scl_namen2id((char *)arg + 1, (int)(arg_end - arg - 1));
if (id == 0) {
semsg(_("E392: No such syntax cluster: %s"), arg);
} else {
@@ -3553,7 +3296,7 @@ static void syn_cmd_list(exarg_T *eap, int syncing)
arg = (char_u *)skipwhite((char *)arg_end);
}
}
- eap->nextcmd = (char *)check_nextcmd(arg);
+ eap->nextcmd = check_nextcmd((char *)arg);
}
static void syn_lines_msg(void)
@@ -3702,7 +3445,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(' ');
@@ -3710,9 +3453,7 @@ static void syn_list_flags(struct name_list *nlist, int flags, int attr)
}
}
-/*
- * List one syntax cluster, for ":syntax" or "syntax list syntax_name".
- */
+// List one syntax cluster, for ":syntax" or "syntax list syntax_name".
static void syn_list_cluster(int id)
{
int endcol = 15;
@@ -3790,14 +3531,14 @@ static void put_pattern(const char *const s, const int c, const synpat_T *const
msg_putchar(c);
// output the pattern, in between a char that is not in the pattern
- for (i = 0; vim_strchr((char *)spp->sp_pattern, sepchars[i]) != NULL;) {
+ for (i = 0; vim_strchr(spp->sp_pattern, sepchars[i]) != NULL;) {
if (sepchars[++i] == NUL) {
i = 0; // no good char found, just use the first one
break;
}
}
msg_putchar(sepchars[i]);
- msg_outtrans((char *)spp->sp_pattern);
+ msg_outtrans(spp->sp_pattern);
msg_putchar(sepchars[i]);
// output any pattern options
@@ -3925,7 +3666,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;
}
@@ -3956,9 +3697,7 @@ static void syn_clear_keyword(int id, hashtab_T *ht)
hash_unlock(ht);
}
-/*
- * Clear a whole keyword table.
- */
+// Clear a whole keyword table.
static void clear_keywtab(hashtab_T *ht)
{
hashitem_T *hi;
@@ -3967,7 +3706,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) {
@@ -3989,13 +3728,14 @@ static void clear_keywtab(hashtab_T *ht)
/// @param flags flags for this keyword
/// @param cont_in_list containedin for this keyword
/// @param next_list nextgroup for this keyword
-static void add_keyword(char_u *const name, const int id, const int flags,
+static void add_keyword(char *const name, const int id, const int flags,
int16_t *const cont_in_list, int16_t *const next_list,
const int conceal_char)
{
- char_u name_folded[MAXKEYWLEN + 1];
- const char_u *const name_ic = (curwin->w_s->b_syn_ic)
- ? str_foldcase(name, (int)STRLEN(name), name_folded, sizeof(name_folded))
+ char name_folded[MAXKEYWLEN + 1];
+ const char *const name_ic = (curwin->w_s->b_syn_ic)
+ ? (char *)str_foldcase((char_u *)name, (int)STRLEN(name), (char_u *)name_folded,
+ sizeof(name_folded))
: name;
keyentry_T *const kp = xmalloc(sizeof(keyentry_T) + STRLEN(name_ic));
@@ -4006,7 +3746,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 +3779,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,13 +3799,13 @@ 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;
+ char *gname_start, *gname;
int syn_id;
int len = 0;
char *p;
@@ -4108,11 +3844,9 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha
}
for (;;) {
- /*
- * This is used very often when a large number of keywords is defined.
- * Need to skip quickly when no option name is found.
- * Also avoid tolower(), it's slow.
- */
+ // This is used very often when a large number of keywords is defined.
+ // Need to skip quickly when no option name is found.
+ // Also avoid tolower(), it's slow.
if (strchr(first_letters, *arg) == NULL) {
break;
}
@@ -4120,8 +3854,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 +3895,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) {
@@ -4183,11 +3917,11 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha
if (gname_start == arg) {
return NULL;
}
- gname = vim_strnsave(gname_start, (size_t)(arg - gname_start));
- if (STRCMP(gname, "NONE") == 0) {
+ gname = xstrnsave(gname_start, (size_t)(arg - gname_start));
+ if (strcmp(gname, "NONE") == 0) {
*opt->sync_idx = NONE_IDX;
} else {
- syn_id = syn_name2id((char *)gname);
+ syn_id = syn_name2id(gname);
int i;
for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0;) {
if (SYN_ITEMS(curwin->w_s)[i].sp_syn.id == syn_id
@@ -4204,7 +3938,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.
@@ -4216,11 +3950,9 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha
return arg;
}
-/*
- * Adjustments to syntax item when declared in a ":syn include"'d file.
- * Set the contained flag, and if the item is not already contained, add it
- * to the specified top-level group, if any.
- */
+// Adjustments to syntax item when declared in a ":syn include"'d file.
+// Set the contained flag, and if the item is not already contained, add it
+// to the specified top-level group, if any.
static void syn_incl_toplevel(int id, int *flagsp)
{
if ((*flagsp & HL_CONTAINED) || curwin->w_s->b_syn_topgrp == 0) {
@@ -4239,21 +3971,19 @@ static void syn_incl_toplevel(int id, int *flagsp)
}
}
-/*
- * Handle ":syntax include [@{group-name}] filename" command.
- */
+// Handle ":syntax include [@{group-name}] filename" command.
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;
}
@@ -4270,13 +4000,11 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
return;
}
// separate_nextcmd() and expand_filename() depend on this
- eap->arg = (char *)rest;
+ eap->arg = rest;
}
- /*
- * Everything that's left, up to the next command, should be the
- * filename to include.
- */
+ // Everything that's left, up to the next command, should be the
+ // filename to include.
eap->argt |= (EX_XFILE | EX_NOSPC);
separate_nextcmd(eap);
if (*eap->arg == '<' || *eap->arg == '$' || path_is_absolute((char_u *)eap->arg)) {
@@ -4292,10 +4020,8 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
}
}
- /*
- * Save and restore the existing top-level grouplist id and ":syn
- * include" tag around the actual inclusion.
- */
+ // Save and restore the existing top-level grouplist id and ":syn
+ // include" tag around the actual inclusion.
if (running_syn_inc_tag >= MAX_SYN_INC_TAG) {
emsg(_("E847: Too many syntax includes"));
return;
@@ -4313,18 +4039,16 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
current_syn_inc_tag = prev_syn_inc_tag;
}
-/*
- * Handle ":syntax keyword {group-name} [{option}] keyword .." command.
- */
+// Handle ":syntax keyword {group-name} [{option}] keyword .." command.
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 +4059,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 +4078,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,7 +4100,7 @@ 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;
}
@@ -4399,7 +4123,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 +4139,12 @@ error:
}
if (rest != NULL) {
- eap->nextcmd = (char *)check_nextcmd(rest);
+ eap->nextcmd = check_nextcmd(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 +4152,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 +4164,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;
@@ -4465,18 +4188,14 @@ static void syn_cmd_match(exarg_T *eap, int syncing)
rest = get_syn_options(rest, &syn_opt_arg, &conceal_char, eap->skip);
if (rest != NULL) { // all arguments are valid
- /*
- * Check for trailing command and illegal trailing arguments.
- */
- eap->nextcmd = (char *)check_nextcmd(rest);
+ // Check for trailing command and illegal trailing arguments.
+ eap->nextcmd = check_nextcmd(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
- */
+ // Store the pattern in the syn_items list
synpat_T *spp = GA_APPEND_VIA_PTR(synpat_T,
&curwin->w_s->b_syn_patterns);
*spp = item;
@@ -4490,7 +4209,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,19 +4218,17 @@ 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
}
}
}
- /*
- * Something failed, free the allocated memory.
- */
+ // Something failed, free the allocated memory.
vim_regfree(item.sp_prog);
xfree(item.sp_pattern);
xfree(syn_opt_arg.cont_list);
@@ -4526,15 +4243,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
@@ -4589,13 +4306,13 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
}
xfree(key);
key = vim_strnsave_up(rest, (size_t)(key_end - rest));
- if (STRCMP(key, "MATCHGROUP") == 0) {
+ if (strcmp(key, "MATCHGROUP") == 0) {
item = ITEM_MATCHGROUP;
- } else if (STRCMP(key, "START") == 0) {
+ } else if (strcmp(key, "START") == 0) {
item = ITEM_START;
- } else if (STRCMP(key, "END") == 0) {
+ } else if (strcmp(key, "END") == 0) {
item = ITEM_END;
- } else if (STRCMP(key, "SKIP") == 0) {
+ } else if (strcmp(key, "SKIP") == 0) {
if (pat_ptrs[ITEM_SKIP] != NULL) { // One skip pattern allowed.
illegal = true;
break;
@@ -4604,13 +4321,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,19 +4338,17 @@ 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
- * syn_patterns for this item, at the start (because the list is
- * used from end to start).
- */
+ // Allocate room for a syn_pattern, and link it in the list of
+ // syn_patterns for this item, at the start (because the list is
+ // used from end to start).
ppp = xmalloc(sizeof(struct pat_ptr));
ppp->pp_next = pat_ptrs[item];
pat_ptrs[item] = ppp;
@@ -4671,22 +4386,18 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
}
if (rest != NULL) {
- /*
- * Check for trailing garbage or command.
- * If OK, add the item.
- */
- eap->nextcmd = (char *)check_nextcmd(rest);
+ // Check for trailing garbage or command.
+ // If OK, add the item.
+ eap->nextcmd = check_nextcmd(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
- */
+ // 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 +4416,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,22 +4424,20 @@ 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
}
}
}
- /*
- * Free the allocated memory.
- */
- for (item = ITEM_START; item <= ITEM_END; ++item) {
+ // Free the allocated memory.
+ 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);
@@ -4771,9 +4480,7 @@ static void syn_combine_list(int16_t **const clstr1, int16_t **const clstr2, con
const int16_t *g2;
int16_t *clstr = NULL;
- /*
- * Handle degenerate cases.
- */
+ // Handle degenerate cases.
if (*clstr2 == NULL) {
return;
}
@@ -4809,13 +4516,9 @@ static void syn_combine_list(int16_t **const clstr1, int16_t **const clstr2, con
g2 = *clstr2;
int count = 0;
- /*
- * First, loop through the lists until one of them is empty.
- */
+ // First, loop through the lists until one of them is empty.
while (*g1 && *g2) {
- /*
- * We always want to add from the first list.
- */
+ // We always want to add from the first list.
if (*g1 < *g2) {
if (round == 2) {
clstr[count] = *g1;
@@ -4824,10 +4527,8 @@ static void syn_combine_list(int16_t **const clstr1, int16_t **const clstr2, con
g1++;
continue;
}
- /*
- * We only want to add from the second list if we're adding the
- * lists.
- */
+ // We only want to add from the second list if we're adding the
+ // lists.
if (list_op == CLUSTER_ADD) {
if (round == 2) {
clstr[count] = *g2;
@@ -4840,11 +4541,9 @@ static void syn_combine_list(int16_t **const clstr1, int16_t **const clstr2, con
g2++;
}
- /*
- * Now add the leftovers from whichever list didn't get finished
- * first. As before, we only want to add from the second list if
- * we're adding the lists.
- */
+ // Now add the leftovers from whichever list didn't get finished
+ // first. As before, we only want to add from the second list if
+ // we're adding the lists.
for (; *g1; g1++, count++) {
if (round == 2) {
clstr[count] = *g1;
@@ -4859,10 +4558,8 @@ static void syn_combine_list(int16_t **const clstr1, int16_t **const clstr2, con
}
if (round == 1) {
- /*
- * If the group ended up empty, we don't need to allocate any
- * space for it.
- */
+ // If the group ended up empty, we don't need to allocate any
+ // space for it.
if (count == 0) {
clstr = NULL;
break;
@@ -4872,24 +4569,22 @@ static void syn_combine_list(int16_t **const clstr1, int16_t **const clstr2, con
}
}
- /*
- * Finally, put the new list in place.
- */
+ // Finally, put the new list in place.
xfree(*clstr1);
xfree(*clstr2);
*clstr1 = clstr;
}
-// Lookup a syntax cluster name and return its ID.
-// If it is not found, 0 is returned.
-static int syn_scl_name2id(char_u *name)
+/// Lookup a syntax cluster name and return its ID.
+/// If it is not found, 0 is returned.
+static int syn_scl_name2id(char *name)
{
// Avoid using stricmp() too much, it's slow on some systems
- char_u *name_u = vim_strsave_up(name);
+ char *name_u = (char *)vim_strsave_up((char_u *)name);
int i;
for (i = curwin->w_s->b_syn_clusters.ga_len; --i >= 0;) {
if (SYN_CLSTR(curwin->w_s)[i].scl_name_u != NULL
- && STRCMP(name_u, SYN_CLSTR(curwin->w_s)[i].scl_name_u) == 0) {
+ && strcmp(name_u, SYN_CLSTR(curwin->w_s)[i].scl_name_u) == 0) {
break;
}
}
@@ -4897,25 +4592,24 @@ static int syn_scl_name2id(char_u *name)
return i < 0 ? 0 : i + SYNID_CLUSTER;
}
-/*
- * Like syn_scl_name2id(), but take a pointer + length argument.
- */
-static int syn_scl_namen2id(char_u *linep, int len)
+/// Like syn_scl_name2id(), but take a pointer + length argument.
+static int syn_scl_namen2id(char *linep, int len)
{
- char_u *name = vim_strnsave(linep, (size_t)len);
+ char *name = xstrnsave(linep, (size_t)len);
int id = syn_scl_name2id(name);
xfree(name);
return id;
}
-// Find syntax cluster name in the table and return its ID.
-// The argument is a pointer to the name and the length of the name.
-// If it doesn't exist yet, a new entry is created.
-// Return 0 for failure.
-static int syn_check_cluster(char_u *pp, int len)
+/// Find syntax cluster name in the table and return its ID.
+/// The argument is a pointer to the name and the length of the name.
+/// If it doesn't exist yet, a new entry is created.
+///
+/// @return 0 for failure.
+static int syn_check_cluster(char *pp, int len)
{
- char_u *name = vim_strnsave(pp, (size_t)len);
+ char *name = xstrnsave(pp, (size_t)len);
int id = syn_scl_name2id(name);
if (id == 0) { // doesn't exist yet
id = syn_add_cluster(name);
@@ -4925,14 +4619,13 @@ static int syn_check_cluster(char_u *pp, int len)
return id;
}
-// Add new syntax cluster and return its ID.
-// "name" must be an allocated string, it will be consumed.
-// Return 0 for failure.
-static int syn_add_cluster(char_u *name)
+/// Add new syntax cluster and return its ID.
+/// "name" must be an allocated string, it will be consumed.
+///
+/// @return 0 for failure.
+static int syn_add_cluster(char *name)
{
- /*
- * First call for this growarray: init growing array.
- */
+ // First call for this growarray: init growing array.
if (curwin->w_s->b_syn_clusters.ga_data == NULL) {
curwin->w_s->b_syn_clusters.ga_itemsize = sizeof(syn_cluster_T);
ga_set_growsize(&curwin->w_s->b_syn_clusters, 10);
@@ -4948,8 +4641,8 @@ static int syn_add_cluster(char_u *name)
syn_cluster_T *scp = GA_APPEND_VIA_PTR(syn_cluster_T,
&curwin->w_s->b_syn_clusters);
CLEAR_POINTER(scp);
- scp->scl_name = name;
- scp->scl_name_u = vim_strsave_up(name);
+ scp->scl_name = (char_u *)name;
+ scp->scl_name_u = (char *)vim_strsave_up((char_u *)name);
scp->scl_list = NULL;
if (STRICMP(name, "Spell") == 0) {
@@ -4962,20 +4655,18 @@ static int syn_add_cluster(char_u *name)
return len + SYNID_CLUSTER;
}
-/*
- * Handle ":syntax cluster {cluster-name} [contains={groupname},..]
- * [add={groupname},..] [remove={groupname},..]".
- */
+// Handle ":syntax cluster {cluster-name} [contains={groupname},..]
+// [add={groupname},..] [remove={groupname},..]".
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;
}
@@ -5021,7 +4712,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.
}
}
@@ -5034,21 +4725,18 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing)
}
}
-/*
- * On first call for current buffer: Init growing array.
- */
+// On first call for current buffer: Init growing array.
static void init_syn_patterns(void)
{
curwin->w_s->b_syn_patterns.ga_itemsize = sizeof(synpat_T);
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 *arg, synpat_T *ci)
{
char *end;
int *p;
@@ -5060,18 +4748,18 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci)
return NULL;
}
- end = (char *)skip_regexp(arg + 1, *arg, true, NULL);
- if (*end != (char)(*arg)) { // end delimiter not found
+ end = skip_regexp(arg + 1, *arg, true, NULL);
+ if (*end != *arg) { // end delimiter not found
semsg(_("E401: Pattern delimiter not found: %s"), arg);
return NULL;
}
// store the pattern and compiled regexp program
- ci->sp_pattern = vim_strnsave(arg + 1, (size_t)(end - (char *)arg) - 1);
+ ci->sp_pattern = xstrnsave(arg + 1, (size_t)(end - arg) - 1);
// Make 'cpoptions' empty, to avoid the 'l' flag
cpo_save = p_cpo;
- p_cpo = "";
- ci->sp_prog = vim_regcomp((char *)ci->sp_pattern, RE_MAGIC);
+ p_cpo = empty_option;
+ ci->sp_prog = vim_regcomp(ci->sp_pattern, RE_MAGIC);
p_cpo = cpo_save;
if (ci->sp_prog == NULL) {
@@ -5080,9 +4768,7 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci)
ci->sp_ic = curwin->w_s->b_syn_ic;
syn_clear_time(&ci->sp_time);
- /*
- * Check for a match, highlight or region offset.
- */
+ // Check for a match, highlight or region offset.
end++;
do {
for (idx = SPO_COUNT; --idx >= 0;) {
@@ -5137,43 +4823,41 @@ 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);
}
-/*
- * Handle ":syntax sync .." command.
- */
+/// Handle ":syntax sync .." command.
static void syn_cmd_sync(exarg_T *eap, int syncing)
{
- char_u *arg_start = (char_u *)eap->arg;
+ char *arg_start = eap->arg;
char *arg_end;
- char_u *key = NULL;
- char_u *next_arg;
+ char *key = NULL;
+ char *next_arg;
int illegal = false;
int finished = false;
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);
- next_arg = (char_u *)skipwhite(arg_end);
+ arg_end = skiptowhite(arg_start);
+ next_arg = skipwhite(arg_end);
xfree(key);
- key = vim_strnsave_up(arg_start, (size_t)(arg_end - (char *)arg_start));
- if (STRCMP(key, "CCOMMENT") == 0) {
+ key = vim_strnsave_up(arg_start, (size_t)(arg_end - arg_start));
+ if (strcmp(key, "CCOMMENT") == 0) {
if (!eap->skip) {
curwin->w_s->b_syn_sync_flags |= SF_CCOMMENT;
}
if (!ends_excmd(*next_arg)) {
- arg_end = (char *)skiptowhite(next_arg);
+ arg_end = skiptowhite(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));
+ (int16_t)syn_check_group(next_arg, (size_t)(arg_end - next_arg));
}
- next_arg = (char_u *)skipwhite(arg_end);
+ next_arg = skipwhite(arg_end);
} else if (!eap->skip) {
curwin->w_s->b_syn_sync_id = (int16_t)syn_name2id("Comment");
}
@@ -5182,14 +4866,14 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
|| STRNCMP(key, "MAXLINES", 8) == 0
|| STRNCMP(key, "LINEBREAKS", 10) == 0) {
if (key[4] == 'S') {
- arg_end = (char *)key + 6;
+ arg_end = key + 6;
} else if (key[0] == 'L') {
- arg_end = (char *)key + 11;
+ arg_end = key + 11;
} else {
- arg_end = (char *)key + 9;
+ arg_end = key + 9;
}
if (arg_end[-1] != '=' || !ascii_isdigit(*arg_end)) {
- illegal = TRUE;
+ illegal = true;
break;
}
linenr_T n = getdigits_int32(&arg_end, false, 0);
@@ -5202,23 +4886,23 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
curwin->w_s->b_syn_sync_minlines = n;
}
}
- } else if (STRCMP(key, "FROMSTART") == 0) {
+ } else if (strcmp(key, "FROMSTART") == 0) {
if (!eap->skip) {
curwin->w_s->b_syn_sync_minlines = MAXLNUM;
curwin->w_s->b_syn_sync_maxlines = 0;
}
- } else if (STRCMP(key, "LINECONT") == 0) {
+ } else if (strcmp(key, "LINECONT") == 0) {
if (*next_arg == NUL) { // missing pattern
illegal = true;
break;
}
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);
- if (*arg_end != (char)(*next_arg)) { // end delimiter not found
+ arg_end = skip_regexp(next_arg + 1, *next_arg, true, NULL);
+ if (*arg_end != *next_arg) { // end delimiter not found
illegal = true;
break;
}
@@ -5226,14 +4910,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);
+ xstrnsave(next_arg + 1, (size_t)(arg_end - 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);
@@ -5243,19 +4927,19 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
break;
}
}
- next_arg = (char_u *)skipwhite(arg_end + 1);
+ next_arg = skipwhite(arg_end + 1);
} else {
- eap->arg = (char *)next_arg;
- if (STRCMP(key, "MATCH") == 0) {
- syn_cmd_match(eap, TRUE);
- } else if (STRCMP(key, "REGION") == 0) {
- syn_cmd_region(eap, TRUE);
- } else if (STRCMP(key, "CLEAR") == 0) {
- syn_cmd_clear(eap, TRUE);
+ eap->arg = next_arg;
+ if (strcmp(key, "MATCH") == 0) {
+ syn_cmd_match(eap, true);
+ } else if (strcmp(key, "REGION") == 0) {
+ syn_cmd_region(eap, true);
+ } else if (strcmp(key, "CLEAR") == 0) {
+ syn_cmd_clear(eap, true);
} else {
- illegal = TRUE;
+ illegal = true;
}
- finished = TRUE;
+ finished = true;
break;
}
arg_start = next_arg;
@@ -5264,8 +4948,8 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
if (illegal) {
semsg(_("E404: Illegal arguments: %s"), arg_start);
} else if (!finished) {
- eap->nextcmd = (char *)check_nextcmd(arg_start);
- redraw_curbuf_later(SOME_VALID);
+ eap->nextcmd = check_nextcmd(arg_start);
+ redraw_curbuf_later(UPD_SOME_VALID);
syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
}
}
@@ -5279,7 +4963,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 +4980,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;
@@ -5313,10 +4997,10 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis
for (end = p; *end && !ascii_iswhite(*end) && *end != ','; end++) {}
char *const name = xmalloc((size_t)(end - p) + 3); // leave room for "^$"
STRLCPY(name + 1, p, end - p + 1);
- if (STRCMP(name + 1, "ALLBUT") == 0
- || STRCMP(name + 1, "ALL") == 0
- || STRCMP(name + 1, "TOP") == 0
- || STRCMP(name + 1, "CONTAINED") == 0) {
+ if (strcmp(name + 1, "ALLBUT") == 0
+ || strcmp(name + 1, "ALL") == 0
+ || strcmp(name + 1, "TOP") == 0
+ || strcmp(name + 1, "CONTAINED") == 0) {
if (TOUPPER_ASC(**arg) != 'C') {
semsg(_("E407: %s not allowed here"), name + 1);
failed = true;
@@ -5345,12 +5029,10 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis
if (skip) {
id = -1;
} else {
- id = syn_check_cluster((char_u *)name + 2, (int)(end - p - 1));
+ id = syn_check_cluster(name + 2, (int)(end - p - 1));
}
} else {
- /*
- * Handle full group name.
- */
+ // Handle full group name.
if (strpbrk(name + 1, "\\.*^$~[") == NULL) {
id = syn_check_group((name + 1), (size_t)(end - p));
} else {
@@ -5364,7 +5046,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 +5103,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;
@@ -5435,9 +5117,7 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis
return OK;
}
-/*
- * Make a copy of an ID list.
- */
+// Make a copy of an ID list.
static int16_t *copy_id_list(const int16_t *const list)
{
if (list == NULL) {
@@ -5472,7 +5152,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,54 +5166,48 @@ 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;
}
- /*
- * If list is ID_LIST_ALL, we are in a transparent item that isn't
- * inside anything. Only allow not-contained groups.
- */
+ // If list is ID_LIST_ALL, we are in a transparent item that isn't
+ // inside anything. Only allow not-contained groups.
if (list == ID_LIST_ALL) {
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;
}
- /*
- * Return "retval" if id is in the contains list.
- */
+ // Return "retval" if id is in the contains list.
while (item != 0) {
if (item == id) {
return retval;
@@ -5585,21 +5259,19 @@ static struct subcommand subcommands[] =
{ NULL, NULL }
};
-/*
- * ":syntax".
- * This searches the subcommands[] table for the subcommand name, and calls a
- * syntax_subcommand() function to do the rest.
- */
+/// ":syntax".
+/// This searches the subcommands[] table for the subcommand name, and calls a
+/// syntax_subcommand() function to do the rest.
void ex_syntax(exarg_T *eap)
{
- char_u *arg = (char_u *)eap->arg;
- char_u *subcmd_end;
+ char *arg = eap->arg;
+ char *subcmd_end;
syn_cmdlinep = eap->cmdlinep;
// isolate subcommand name
for (subcmd_end = arg; ASCII_ISALPHA(*subcmd_end); subcmd_end++) {}
- char_u *const subcmd_name = vim_strnsave(arg, (size_t)(subcmd_end - arg));
+ char *const subcmd_name = xstrnsave(arg, (size_t)(subcmd_end - arg));
if (eap->skip) { // skip error messages for all subcommands
emsg_skip++;
}
@@ -5608,8 +5280,8 @@ void ex_syntax(exarg_T *eap)
semsg(_("E410: Invalid :syntax subcommand: %s"), subcmd_name);
break;
}
- if (STRCMP(subcmd_name, (char_u *)subcommands[i].name) == 0) {
- eap->arg = skipwhite((char *)subcmd_end);
+ if (strcmp(subcmd_name, subcommands[i].name) == 0) {
+ eap->arg = skipwhite(subcmd_end);
(subcommands[i].func)(eap, false);
break;
}
@@ -5622,8 +5294,8 @@ void ex_syntax(exarg_T *eap)
void ex_ownsyntax(exarg_T *eap)
{
- char_u *old_value;
- char_u *new_value;
+ char *old_value;
+ char *new_value;
if (curwin->w_s == &curwin->w_buffer->b_s) {
curwin->w_s = xcalloc(1, sizeof(synblock_T));
@@ -5640,25 +5312,25 @@ void ex_ownsyntax(exarg_T *eap)
}
// Save value of b:current_syntax.
- old_value = get_var_value("b:current_syntax");
+ old_value = (char *)get_var_value("b:current_syntax");
if (old_value != NULL) {
- old_value = vim_strsave(old_value);
+ old_value = xstrdup(old_value);
}
// Apply the "syntax" autocommand event, this finds and loads the syntax file.
apply_autocmds(EVENT_SYNTAX, eap->arg, curbuf->b_fname, true, curbuf);
// Move value of b:current_syntax to w:current_syntax.
- new_value = get_var_value("b:current_syntax");
+ new_value = (char *)get_var_value("b:current_syntax");
if (new_value != NULL) {
- set_internal_string_var("w:current_syntax", (char *)new_value);
+ set_internal_string_var("w:current_syntax", new_value);
}
// Restore value of b:current_syntax.
if (old_value == NULL) {
do_unlet(S_LEN("b:current_syntax"), true);
} else {
- set_internal_string_var("b:current_syntax", (char *)old_value);
+ set_internal_string_var("b:current_syntax", old_value);
xfree(old_value);
}
}
@@ -5675,22 +5347,19 @@ 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;
-/*
- * Reset include_link, include_default, include_none to 0.
- * Called when we are done expanding.
- */
+// Reset include_link, include_default, include_none to 0.
+// Called when we are done expanding.
void reset_expand_highlight(void)
{
include_link = include_default = include_none = 0;
}
-/*
- * Handle command line completion for :match and :echohl command: Add "None"
- * as highlight group.
- */
+// Handle command line completion for :match and :echohl command: Add "None"
+// as highlight group.
void set_context_in_echohl_cmd(expand_T *xp, const char *arg)
{
xp->xp_context = EXPAND_HIGHLIGHT;
@@ -5698,9 +5367,7 @@ void set_context_in_echohl_cmd(expand_T *xp, const char *arg)
include_none = 1;
}
-/*
- * Handle command line completion for :syntax command.
- */
+// Handle command line completion for :syntax command.
void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
{
// Default: expand subcommands.
@@ -5712,10 +5379,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 +5390,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;
@@ -5735,10 +5408,8 @@ void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
}
}
-/*
- * Function given to ExpandGeneric() to obtain the list syntax names for
- * expansion.
- */
+// Function given to ExpandGeneric() to obtain the list syntax names for
+// expansion.
char *get_syntax_name(expand_T *xp, int idx)
{
switch (expand_what) {
@@ -5760,6 +5431,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;
}
@@ -5786,12 +5465,10 @@ int syn_get_id(win_T *wp, linenr_T lnum, colnr_T col, int trans, bool *spellp, i
return trans ? current_trans_id : current_id;
}
-/*
- * Get extra information about the syntax item. Must be called right after
- * get_syntax_attr().
- * Stores the current item sequence nr in "*seqnrp".
- * Returns the current flags.
- */
+// Get extra information about the syntax item. Must be called right after
+// get_syntax_attr().
+// Stores the current item sequence nr in "*seqnrp".
+// Returns the current flags.
int get_syntax_info(int *seqnrp)
{
*seqnrp = current_seqnr;
@@ -5815,24 +5492,20 @@ int syn_get_concealed_id(win_T *wp, linenr_T lnum, colnr_T col)
return 0;
}
-/*
- * Return conceal substitution character
- */
+// Return conceal substitution character
int syn_get_sub_char(void)
{
return current_sub_char;
}
-/*
- * Return the syntax ID at position "i" in the current stack.
- * The caller must have called syn_get_id() before to fill the stack.
- * Returns -1 when "i" is out of range.
- */
+// Return the syntax ID at position "i" in the current stack.
+// The caller must have called syn_get_id() before to fill the stack.
+// Returns -1 when "i" is out of range.
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;
@@ -5890,18 +5563,16 @@ int syn_get_foldlevel(win_T *wp, linenr_T lnum)
return level;
}
-/*
- * ":syntime".
- */
+// ":syntime".
void ex_syntime(exarg_T *eap)
{
- if (STRCMP(eap->arg, "on") == 0) {
+ if (strcmp(eap->arg, "on") == 0) {
syn_time_on = true;
- } else if (STRCMP(eap->arg, "off") == 0) {
+ } else if (strcmp(eap->arg, "off") == 0) {
syn_time_on = false;
- } else if (STRCMP(eap->arg, "clear") == 0) {
+ } else if (strcmp(eap->arg, "clear") == 0) {
syntime_clear();
- } else if (STRCMP(eap->arg, "report") == 0) {
+ } else if (strcmp(eap->arg, "report") == 0) {
syntime_report();
} else {
semsg(_(e_invarg2), eap->arg);
@@ -5916,9 +5587,7 @@ static void syn_clear_time(syn_time_T *st)
st->match = 0;
}
-/*
- * Clear the syntax timing for the current buffer.
- */
+// Clear the syntax timing for the current buffer.
static void syntime_clear(void)
{
synpat_T *spp;
@@ -5927,16 +5596,14 @@ 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);
}
}
-/*
- * Function given to ExpandGeneric() to obtain the possible arguments of the
- * ":syntime {on,off,clear,report}" command.
- */
+// Function given to ExpandGeneric() to obtain the possible arguments of the
+// ":syntime {on,off,clear,report}" command.
char *get_syntime_arg(expand_T *xp, int idx)
{
switch (idx) {
@@ -5960,9 +5627,7 @@ static int syn_compare_syntime(const void *v1, const void *v2)
return profile_cmp(s1->total, s2->total);
}
-/*
- * Clear the syntax timing for the current buffer.
- */
+// Clear the syntax timing for the current buffer.
static void syntime_report(void)
{
if (!syntax_present(curwin)) {
@@ -5976,7 +5641,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);
@@ -5989,7 +5654,7 @@ static void syntime_report(void)
proftime_T tm = profile_divide(spp->sp_time.total, (int)spp->sp_time.count);
p->average = tm;
p->id = spp->sp_syn.id;
- p->pattern = spp->sp_pattern;
+ p->pattern = (char_u *)spp->sp_pattern;
}
}
@@ -6002,7 +5667,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 +5698,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..36f797da06 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -1,9 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * Code to handle tags and the tag stack
- */
+// Code to handle tags and the tag stack
#include <assert.h>
#include <inttypes.h>
@@ -51,12 +49,10 @@
#include "nvim/vim.h"
#include "nvim/window.h"
-/*
- * Structure to hold pointers to various items in a tag line.
- */
+// Structure to hold pointers to various items in a tag line.
typedef struct tag_pointers {
// filled in by parse_tag_line():
- char_u *tagname; // start of tag name (skip "file:")
+ char *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
@@ -65,16 +61,14 @@ typedef struct tag_pointers {
char_u *command_end; // first char after command
char_u *tag_fname; // file name of the tags file. This is used
// when 'tr' is set.
- char_u *tagkind; // "kind:" value
- char_u *tagkind_end; // end of tagkind
- char_u *user_data; // user_data string
+ char_u *tagkind; // "kind:" value
+ char_u *tagkind_end; // end of tagkind
+ char *user_data; // user_data string
char_u *user_data_end; // end of user_data
- linenr_T tagline; // "line:" value
+ linenr_T tagline; // "line:" value
} tagptrs_T;
-/*
- * Structure to hold info about the tag pattern being used.
- */
+// Structure to hold info about the tag pattern being used.
typedef struct {
char_u *pat; // the pattern
int len; // length of pat[]
@@ -101,7 +95,7 @@ static char *mt_names[MT_COUNT/2] =
{ "FSC", "F C", "F ", "FS ", " SC", " C", " ", " S " };
#define NOTAGFILE 99 // return value for jumpto_tag
-static char_u *nofile_fname = NULL; // fname for NOTAGFILE error
+static char *nofile_fname = NULL; // fname for NOTAGFILE error
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "tag.c.generated.h"
@@ -114,12 +108,10 @@ static char_u *recurmsg
static char_u *tfu_inv_ret_msg
= (char_u *)N_("E987: invalid return value from tagfunc");
-static char_u *tagmatchname = NULL; // name of last used tag
+static char *tagmatchname = NULL; // name of last used tag
-/*
- * Tag for preview window is remembered separately, to avoid messing up the
- * normal tagstack.
- */
+// Tag for preview window is remembered separately, to avoid messing up the
+// normal tagstack.
static taggy_T ptag_entry = { NULL, INIT_FMARK, 0, 0, NULL };
static int tfu_in_use = false; // disallow recursive call of tagfunc
@@ -149,7 +141,7 @@ static int tfu_in_use = false; // disallow recursive call of tagfunc
/// @param tag tag (pattern) to jump to
/// @param forceit :ta with !
/// @param verbose print "tag not found" message
-bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
+bool do_tag(char *tag, int type, int count, int forceit, int verbose)
{
taggy_T *tagstack = curwin->w_tagstack;
int tagstackidx = curwin->w_tagstackidx;
@@ -215,7 +207,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 = xstrdup(tag);
}
} else {
if (g_do_tagpreview != 0) {
@@ -232,20 +224,18 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
)) {
if (g_do_tagpreview != 0) {
if (ptag_entry.tagname != NULL
- && STRCMP(ptag_entry.tagname, tag) == 0) {
+ && strcmp(ptag_entry.tagname, tag) == 0) {
// Jumping to same tag: keep the current match, so that
// the CursorHold autocommand example works.
cur_match = ptag_entry.cur_match;
cur_fnum = ptag_entry.cur_fnum;
} else {
tagstack_clear_entry(&ptag_entry);
- ptag_entry.tagname = vim_strsave(tag);
+ ptag_entry.tagname = xstrdup(tag);
}
} else {
- /*
- * If the last used entry is not at the top, delete all tag
- * stack entries above it.
- */
+ // If the last used entry is not at the top, delete all tag
+ // stack entries above it.
while (tagstackidx < tagstacklen) {
tagstack_clear_entry(&tagstack[--tagstacklen]);
}
@@ -261,7 +251,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 = xstrdup(tag);
curwin->w_tagstacklen = tagstacklen;
@@ -299,10 +289,8 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
// tagstack before it's used.
saved_fmark = tagstack[tagstackidx].fmark;
if (saved_fmark.fnum != curbuf->b_fnum) {
- /*
- * Jump to other file. If this fails (e.g. because the
- * file was changed) keep original position in tag stack.
- */
+ // Jump to other file. If this fails (e.g. because the
+ // file was changed) keep original position in tag stack.
if (buflist_getfile(saved_fmark.fnum, saved_fmark.mark.lnum,
GETF_SETMARK, forceit) == FAIL) {
tagstackidx = oldtagstackidx; // back to old posn
@@ -339,11 +327,9 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
// ":tag" (no argument): go to newer pattern
save_pos = true; // save the cursor position below
if ((tagstackidx += count - 1) >= tagstacklen) {
- /*
- * Beyond the last one, just give an error message and
- * go to the last one. Don't store the cursor
- * position.
- */
+ // Beyond the last one, just give an error message and
+ // go to the last one. Don't store the cursor
+ // position.
tagstackidx = tagstacklen - 1;
emsg(_(topmsg));
save_pos = false;
@@ -400,9 +386,7 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
ptag_entry.cur_fnum = cur_fnum;
}
} else {
- /*
- * For ":tag [arg]" or ":tselect" remember position before the jump.
- */
+ // For ":tag [arg]" or ":tselect" remember position before the jump.
saved_fmark = tagstack[tagstackidx].fmark;
if (save_pos) {
tagstack[tagstackidx].fmark.mark = curwin->w_cursor;
@@ -431,12 +415,10 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
}
}
- /*
- * Repeat searching for tags, when a file has not been found.
- */
+ // Repeat searching for tags, when a file has not been found.
for (;;) {
int other_name;
- char_u *name;
+ char *name;
// When desired match not found yet, try to find it (and others).
if (use_tagstack) {
@@ -446,13 +428,13 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
} else {
name = tag;
}
- other_name = (tagmatchname == NULL || STRCMP(tagmatchname, name) != 0);
+ other_name = (tagmatchname == NULL || strcmp(tagmatchname, name) != 0);
if (new_tag
|| (cur_match >= num_matches && max_num_matches != MAXCOL)
|| other_name) {
if (other_name) {
xfree(tagmatchname);
- tagmatchname = vim_strsave(name);
+ tagmatchname = xstrdup(name);
}
if (type == DT_SELECT || type == DT_JUMP
@@ -484,7 +466,7 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
}
if (find_tags(name, &new_num_matches, &new_matches, flags,
- max_num_matches, buf_ffname) == OK
+ 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.
@@ -501,10 +483,10 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
// Find the position of each old match in the new list. Need
// to use parse_match() to find the tag line.
for (j = 0; j < num_matches; j++) {
- parse_match((char_u *)matches[j], &tagp);
+ parse_match(matches[j], &tagp);
for (i = idx; i < new_num_matches; i++) {
- parse_match((char_u *)new_matches[i], &tagp2);
- if (STRCMP(tagp.tagname, tagp2.tagname) == 0) {
+ parse_match(new_matches[i], &tagp2);
+ if (strcmp(tagp.tagname, tagp2.tagname) == 0) {
char_u *p = (char_u *)new_matches[i];
for (k = i; k > idx; k--) {
new_matches[k] = new_matches[k - 1];
@@ -539,7 +521,7 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
print_tag_list(new_tag, use_tagstack, num_matches, matches);
ask_for_selection = true;
} else if (type == DT_LTAG) {
- if (add_llist_tags(tag, num_matches, matches) == FAIL) {
+ if (add_llist_tags((char_u *)tag, num_matches, matches) == FAIL) {
goto end_do_tag;
}
@@ -584,12 +566,11 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
tagstack[tagstackidx].cur_fnum = cur_fnum;
// store user-provided data originating from tagfunc
- if (use_tfu && parse_match((char_u *)matches[cur_match], &tagp2) == OK
+ if (use_tfu && parse_match(matches[cur_match], &tagp2) == OK
&& tagp2.user_data) {
XFREE_CLEAR(tagstack[tagstackidx].user_data);
- tagstack[tagstackidx].user_data = vim_strnsave(tagp2.user_data,
- (size_t)(tagp2.user_data_end -
- tagp2.user_data));
+ tagstack[tagstackidx].user_data =
+ xstrnsave(tagp2.user_data, (size_t)(tagp2.user_data_end - (char_u *)tagp2.user_data));
}
tagstackidx++;
@@ -598,10 +579,8 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
ptag_entry.cur_fnum = cur_fnum;
}
- /*
- * Only when going to try the next match, report that the previous
- * file didn't exist. Otherwise an emsg() is given below.
- */
+ // Only when going to try the next match, report that the previous
+ // file didn't exist. Otherwise an emsg() is given below.
if (nofile_fname != NULL && error_cur_match != cur_match) {
smsg(_("File \"%s\" does not exist"), nofile_fname);
}
@@ -640,9 +619,7 @@ bool do_tag(char_u *tag, int type, int count, int forceit, int verbose)
vim_snprintf((char *)IObuff, IOSIZE, ":ta %s\r", name);
set_vim_var_string(VV_SWAPCOMMAND, (char *)IObuff, -1);
- /*
- * Jump to the desired match.
- */
+ // Jump to the desired match.
i = jumpto_tag((char_u *)matches[cur_match], forceit, type != DT_CSCOPE);
set_vim_var_string(VV_SWAPCOMMAND, NULL, -1);
@@ -704,8 +681,8 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char
// Assume that the first match indicates how long the tags can
// be, and align the file names to that.
- parse_match((char_u *)matches[0], &tagp);
- taglen = (int)(tagp.tagname_end - tagp.tagname + 2);
+ parse_match(matches[0], &tagp);
+ taglen = (int)(tagp.tagname_end - (char_u *)tagp.tagname + 2);
if (taglen < 18) {
taglen = 18;
}
@@ -722,7 +699,7 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char
msg_puts_attr(_("file\n"), HL_ATTR(HLF_T));
for (i = 0; i < num_matches && !got_int; i++) {
- parse_match((char_u *)matches[i], &tagp);
+ parse_match(matches[i], &tagp);
if (!new_tag && (
(g_do_tagpreview != 0
&& i == ptag_entry.cur_match)
@@ -737,12 +714,12 @@ 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);
msg_outtrans_len_attr(tagp.tagname,
- (int)(tagp.tagname_end - tagp.tagname),
+ (int)(tagp.tagname_end - (char_u *)tagp.tagname),
HL_ATTR(HLF_T));
msg_putchar(' ');
taglen_advance(taglen);
@@ -751,7 +728,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 +770,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 +828,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 "$?;\""
@@ -896,10 +873,10 @@ static int add_llist_tags(char_u *tag, int num_matches, char **matches)
long lnum;
dict_T *dict;
- parse_match((char_u *)matches[i], &tagp);
+ parse_match(matches[i], &tagp);
// Save the tag name
- len = (int)(tagp.tagname_end - tagp.tagname);
+ len = (int)(tagp.tagname_end - (char_u *)tagp.tagname);
if (len > 128) {
len = 128;
}
@@ -1005,9 +982,7 @@ static int add_llist_tags(char_u *tag, int num_matches, char **matches)
return OK;
}
-/*
- * Free cached tags.
- */
+// Free cached tags.
void tag_freematch(void)
{
XFREE_CLEAR(tagmatchname);
@@ -1023,9 +998,7 @@ static void taglen_advance(int l)
}
}
-/*
- * Print the tag stack
- */
+// Print the tag stack
void do_tags(exarg_T *eap)
{
int i;
@@ -1036,7 +1009,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,22 +1024,19 @@ 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);
}
- ui_flush(); // show one line at a time
}
if (tagstackidx == tagstacklen) { // idx at top of stack
msg_puts("\n>");
}
}
-/*
- * Compare two strings, for length "len", ignoring case the ASCII way.
- * return 0 for match, < 0 for smaller, > 0 for bigger
- * Make sure case is folded to uppercase in comparison (like for 'sort -f')
- */
+// Compare two strings, for length "len", ignoring case the ASCII way.
+// return 0 for match, < 0 for smaller, > 0 for bigger
+// Make sure case is folded to uppercase in comparison (like for 'sort -f')
static int tag_strnicmp(char_u *s1, char_u *s2, size_t len)
{
int i;
@@ -1086,9 +1056,7 @@ static int tag_strnicmp(char_u *s1, char_u *s2, size_t len)
return 0; // strings match
}
-/*
- * Extract info from the tag search pattern "pats->pat".
- */
+// Extract info from the tag search pattern "pats->pat".
static void prepare_pats(pat_T *pats, int has_re)
{
pats->head = pats->pat;
@@ -1184,7 +1152,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--;
@@ -1203,7 +1171,7 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl
taglist = rettv.vval.v_list;
TV_LIST_ITER_CONST(taglist, li, {
- char_u *res_name;
+ char *res_name;
char_u *res_fname;
char_u *res_cmd;
char_u *res_kind;
@@ -1222,28 +1190,28 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl
res_kind = NULL;
TV_DICT_ITER(TV_LIST_ITEM_TV(li)->vval.v_dict, di, {
- const char_u *dict_key = di->di_key;
+ const char *dict_key = (char *)di->di_key;
typval_T *tv = &di->di_tv;
if (tv->v_type != VAR_STRING || tv->vval.v_string == NULL) {
continue;
}
- len += STRLEN(tv->vval.v_string) + 1; // Space for "\tVALUE"
- if (!STRCMP(dict_key, "name")) {
- res_name = (char_u *)tv->vval.v_string;
+ len += strlen(tv->vval.v_string) + 1; // Space for "\tVALUE"
+ if (!strcmp(dict_key, "name")) {
+ res_name = tv->vval.v_string;
continue;
}
- if (!STRCMP(dict_key, "filename")) {
+ if (!strcmp(dict_key, "filename")) {
res_fname = (char_u *)tv->vval.v_string;
continue;
}
- if (!STRCMP(dict_key, "cmd")) {
+ if (!strcmp(dict_key, "cmd")) {
res_cmd = (char_u *)tv->vval.v_string;
continue;
}
has_extra = 1;
- if (!STRCMP(dict_key, "kind")) {
+ if (!strcmp(dict_key, "kind")) {
res_kind = (char_u *)tv->vval.v_string;
continue;
}
@@ -1261,10 +1229,10 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl
break;
}
- char_u *const mfp = name_only ? vim_strsave(res_name) : xmalloc(len + 2);
+ char *const mfp = name_only ? xstrdup(res_name) : xmalloc(len + 2);
if (!name_only) {
- char_u *p = mfp;
+ char_u *p = (char_u *)mfp;
*p++ = MT_GL_OTH + 1; // mtt
*p++ = TAG_SEP; // no tag file name
@@ -1291,22 +1259,22 @@ static int find_tagfunc_tags(char_u *pat, garray_T *ga, int *match_count, int fl
}
TV_DICT_ITER(TV_LIST_ITEM_TV(li)->vval.v_dict, di, {
- const char_u *dict_key = di->di_key;
+ const char *dict_key = (char *)di->di_key;
typval_T *tv = &di->di_tv;
if (tv->v_type != VAR_STRING || tv->vval.v_string == NULL) {
continue;
}
- if (!STRCMP(dict_key, "name")) {
+ if (!strcmp(dict_key, "name")) {
continue;
}
- if (!STRCMP(dict_key, "filename")) {
+ if (!strcmp(dict_key, "filename")) {
continue;
}
- if (!STRCMP(dict_key, "cmd")) {
+ if (!strcmp(dict_key, "cmd")) {
continue;
}
- if (!STRCMP(dict_key, "kind")) {
+ if (!strcmp(dict_key, "kind")) {
continue;
}
@@ -1365,8 +1333,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 +1377,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;
@@ -1425,7 +1393,7 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
int help_pri = 0;
char_u *help_lang_find = NULL; // lang to be found
char_u help_lang[3]; // lang of current tags file
- char_u *saved_pat = NULL; // copy of pat[]
+ char *saved_pat = NULL; // copy of pat[]
bool is_txt = false;
pat_T orgpat; // holds unconverted pattern info
@@ -1441,7 +1409,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,23 +1427,21 @@ 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;
- /*
- * Allocate memory for the buffers that are used
- */
+ // Allocate memory for the buffers that are used
lbuf = xmalloc((size_t)lbuf_size);
tag_fname = xmalloc(MAXPATHL + 1);
for (mtt = 0; mtt < MT_COUNT; mtt++) {
@@ -1485,9 +1451,7 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
STRCPY(tag_fname, "from cscope"); // for error messages
- /*
- * Initialize a few variables
- */
+ // Initialize a few variables
if (help_only) { // want tags from help file
curbuf->b_help = true; // will be restored later
} else if (use_cscope) {
@@ -1496,16 +1460,16 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
curbuf->b_help = false;
}
- orgpat.len = (int)STRLEN(pat);
+ orgpat.len = (int)strlen(pat);
if (curbuf->b_help) {
// When "@ab" is specified use only the "ab" language, otherwise
// search all languages.
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];
- orgpat.pat = saved_pat;
+ saved_pat = xstrnsave(pat, (size_t)orgpat.len - 3);
+ help_lang_find = (char_u *)&pat[orgpat.len - 2];
+ orgpat.pat = (char_u *)saved_pat;
orgpat.len -= 3;
}
}
@@ -1514,7 +1478,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,40 +1491,39 @@ 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;
}
}
- /*
- * When finding a specified number of matches, first try with matching
- * case, so binary search can be used, and try ignore-case matches in a
- * second loop.
- * When finding all matches, 'tagbsearch' is off, or there is no fixed
- * string to look for, ignore case right away to avoid going though the
- * tags files twice.
- * When the tag file is case-fold sorted, it is either one or the other.
- * Only ignore case when TAG_NOIC not used or 'ignorecase' set.
- */
+ // When finding a specified number of matches, first try with matching
+ // case, so binary search can be used, and try ignore-case matches in a
+ // second loop.
+ // When finding all matches, 'tagbsearch' is off, or there is no fixed
+ // string to look for, ignore case right away to avoid going though the
+ // tags files twice.
+ // When the tag file is case-fold sorted, it is either one or the other.
+ // Only ignore case when TAG_NOIC not used or 'ignorecase' set.
+
// Set a flag if the file extension is .txt
if ((flags & TAG_KEEP_LANG)
&& help_lang_find == NULL
&& curbuf->b_fname != NULL
- && (i = (int)STRLEN(curbuf->b_fname)) > 4
+ && (i = (int)strlen(curbuf->b_fname)) > 4
&& STRICMP(curbuf->b_fname + i - 4, ".txt") == 0) {
is_txt = true;
}
orgpat.regmatch.rm_ic = ((p_ic || !noic)
&& (findall || orgpat.headlen == 0 || !p_tbs));
- for (round = 1; round <= 2; ++round) {
+ 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).
@@ -1594,14 +1557,14 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
if ((flags & TAG_KEEP_LANG)
&& help_lang_find == NULL
&& curbuf->b_fname != NULL
- && (i = (int)STRLEN(curbuf->b_fname)) > 4
+ && (i = (int)strlen(curbuf->b_fname)) > 4
&& curbuf->b_fname[i - 1] == 'x'
&& curbuf->b_fname[i - 4] == '.'
&& STRNICMP(curbuf->b_fname + i - 3, help_lang, 2) == 0) {
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;
}
@@ -1635,9 +1598,7 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
state = TS_START; // we're at the start of the file
- /*
- * Read and parse the lines in the file one by one
- */
+ // Read and parse the lines in the file one by one
for (;;) {
// check for CTRL-C typed, more often when jumping around
if (state == TS_BINARY || state == TS_SKIP_BACK) {
@@ -1662,9 +1623,7 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
if (get_it_again) {
goto line_read_in;
}
- /*
- * For binary search: compute the next offset to use.
- */
+ // For binary search: compute the next offset to use.
if (state == TS_BINARY) {
offset = search_info.low_offset + ((search_info.high_offset
- search_info.low_offset) / 2);
@@ -1683,10 +1642,8 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
}
}
- /*
- * When jumping around in the file, first read a line to find the
- * start of the next line.
- */
+ // When jumping around in the file, first read a line to find the
+ // start of the next line.
if (state == TS_BINARY || state == TS_SKIP_BACK) {
// Adjust the search file offset to the correct position
search_info.curr_offset_used = search_info.curr_offset;
@@ -1704,7 +1661,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);
}
@@ -1715,17 +1672,15 @@ int find_tags(char_u *pat, int *num_matches, char ***matchesp, int flags, int mi
search_info.curr_offset = search_info.curr_offset_used;
continue;
}
- }
- /*
- * Not jumping around in the file: Read the next line.
- */
- else {
+ } else {
+ // Not jumping around in the file: Read the next line.
+
// skip empty and blank lines
do {
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 +1695,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;
@@ -1755,10 +1710,8 @@ line_read_in:
}
}
- /*
- * When still at the start of the file, check for Emacs tags file
- * format, and for "not sorted" flag.
- */
+ // When still at the start of the file, check for Emacs tags file
+ // format, and for "not sorted" flag.
if (state == TS_START) {
// The header ends when the line sorts below "!_TAG_". When
// case is folded lower case letters sort before "_".
@@ -1769,9 +1722,7 @@ line_read_in:
goto parse_line;
}
- /*
- * Read header line.
- */
+ // Read header line.
if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) {
tag_file_sorted = lbuf[18];
}
@@ -1780,7 +1731,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.
@@ -1789,15 +1740,13 @@ line_read_in:
// Headers ends.
- /*
- * When there is no tag head, or ignoring case, need to do a
- * linear search.
- * When no "!_TAG_" is found, default to binary search. If
- * the tag file isn't sorted, the second loop will find it.
- * When "!_TAG_FILE_SORTED" found: start binary search if
- * flag set.
- * For cscope, it's always linear.
- */
+ // When there is no tag head, or ignoring case, need to do a
+ // linear search.
+ // When no "!_TAG_" is found, default to binary search. If
+ // the tag file isn't sorted, the second loop will find it.
+ // When "!_TAG_FILE_SORTED" found: start binary search if
+ // flag set.
+ // For cscope, it's always linear.
if (linear || use_cscope) {
state = TS_LINEAR;
} else if (tag_file_sorted == NUL) {
@@ -1864,7 +1813,7 @@ parse_line:
// This speeds up tag searching a lot!
if (orgpat.headlen) {
CLEAR_FIELD(tagp);
- tagp.tagname = lbuf;
+ tagp.tagname = (char *)lbuf;
tagp.tagname_end = (char_u *)vim_strchr((char *)lbuf, TAB);
if (tagp.tagname_end == NULL) {
// Corrupted tag line.
@@ -1872,11 +1821,9 @@ parse_line:
break;
}
- /*
- * Skip this line if the length of the tag is different and
- * there is no regexp, or the tag is too short.
- */
- cmplen = (int)(tagp.tagname_end - tagp.tagname);
+ // Skip this line if the length of the tag is different and
+ // there is no regexp, or the tag is too short.
+ cmplen = (int)(tagp.tagname_end - (char_u *)tagp.tagname);
if (p_tl != 0 && cmplen > p_tl) { // adjust for 'taglength'
cmplen = (int)p_tl;
}
@@ -1887,9 +1834,7 @@ parse_line:
}
if (state == TS_BINARY) {
- /*
- * Simplistic check for unsorted tags file.
- */
+ // Simplistic check for unsorted tags file.
i = (int)tagp.tagname[0];
if (sortic) {
i = TOUPPER_ASC(tagp.tagname[0]);
@@ -1898,20 +1843,16 @@ parse_line:
sort_error = true;
}
- /*
- * Compare the current tag with the searched tag.
- */
+ // Compare the current tag with the searched tag.
if (sortic) {
- tagcmp = tag_strnicmp(tagp.tagname, orgpat.head,
+ tagcmp = tag_strnicmp((char_u *)tagp.tagname, orgpat.head,
(size_t)cmplen);
} else {
tagcmp = STRNCMP(tagp.tagname, orgpat.head, cmplen);
}
- /*
- * A match with a shorter tag means to search forward.
- * A match with a longer tag means to search backward.
- */
+ // A match with a shorter tag means to search forward.
+ // A match with a longer tag means to search backward.
if (tagcmp == 0) {
if (cmplen < orgpat.headlen) {
tagcmp = -1;
@@ -1935,7 +1876,7 @@ parse_line:
search_info.low_char =
TOUPPER_ASC(tagp.tagname[0]);
} else {
- search_info.low_char = tagp.tagname[0];
+ search_info.low_char = (uint8_t)tagp.tagname[0];
}
continue;
}
@@ -1947,7 +1888,7 @@ parse_line:
search_info.high_char =
TOUPPER_ASC(tagp.tagname[0]);
} else {
- search_info.high_char = tagp.tagname[0];
+ search_info.high_char = (uint8_t)tagp.tagname[0];
}
continue;
}
@@ -1956,7 +1897,7 @@ parse_line:
break;
} else if (state == TS_SKIP_BACK) {
assert(cmplen >= 0);
- if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) {
+ if (mb_strnicmp(tagp.tagname, (char *)orgpat.head, (size_t)cmplen) != 0) {
state = TS_STEP_FORWARD;
} else {
// Have to skip back more. Restore the curr_offset
@@ -1966,7 +1907,7 @@ parse_line:
continue;
} else if (state == TS_STEP_FORWARD) {
assert(cmplen >= 0);
- if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) {
+ if (mb_strnicmp(tagp.tagname, (char *)orgpat.head, (size_t)cmplen) != 0) {
if ((off_T)vim_ftell(fp) > search_info.match_offset) {
break; // past last match
} else {
@@ -1977,7 +1918,7 @@ parse_line:
// skip this match if it can't match
assert(cmplen >= 0);
}
- if (mb_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen) != 0) {
+ if (mb_strnicmp(tagp.tagname, (char *)orgpat.head, (size_t)cmplen) != 0) {
continue;
}
@@ -1999,21 +1940,19 @@ parse_line:
break;
}
- /*
- * First try matching with the pattern literally (also when it is
- * a regexp).
- */
- cmplen = (int)(tagp.tagname_end - tagp.tagname);
+ // First try matching with the pattern literally (also when it is
+ // a regexp).
+ cmplen = (int)(tagp.tagname_end - (char_u *)tagp.tagname);
if (p_tl != 0 && cmplen > p_tl) { // adjust for 'taglength'
cmplen = (int)p_tl;
}
// 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);
- match = mb_strnicmp(tagp.tagname, orgpat.pat, (size_t)cmplen) == 0;
+ match = mb_strnicmp(tagp.tagname, (char *)orgpat.pat, (size_t)cmplen) == 0;
if (match) {
match_no_ic = (STRNCMP(tagp.tagname, orgpat.pat,
cmplen) == 0);
@@ -2023,21 +1962,19 @@ parse_line:
}
}
- /*
- * Has a regexp: Also find tags matching regexp.
- */
- match_re = FALSE;
+ // Has a regexp: Also find tags matching regexp.
+ match_re = false;
if (!match && orgpat.regmatch.regprog != NULL) {
int cc;
cc = *tagp.tagname_end;
*tagp.tagname_end = NUL;
- match = vim_regexec(&orgpat.regmatch, (char *)tagp.tagname, (colnr_T)0);
+ match = vim_regexec(&orgpat.regmatch, tagp.tagname, (colnr_T)0);
if (match) {
matchoff = (int)(orgpat.regmatch.startp[0] - tagp.tagname);
if (orgpat.regmatch.rm_ic) {
orgpat.regmatch.rm_ic = false;
- match_no_ic = vim_regexec(&orgpat.regmatch, (char *)tagp.tagname, (colnr_T)0);
+ match_no_ic = vim_regexec(&orgpat.regmatch, tagp.tagname, (colnr_T)0);
orgpat.regmatch.rm_ic = true;
}
}
@@ -2054,7 +1991,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);
@@ -2090,7 +2028,7 @@ parse_line:
// detecting duplicates.
// The format is {tagname}@{lang}NUL{heuristic}NUL
*tagp.tagname_end = NUL;
- len = (size_t)(tagp.tagname_end - tagp.tagname);
+ len = (size_t)(tagp.tagname_end - (char_u *)tagp.tagname);
mfp = xmalloc(sizeof(char) + len + 10 + ML_EXTRA + 1);
p = (char_u *)mfp;
@@ -2098,7 +2036,7 @@ parse_line:
p[len] = '@';
STRCPY(p + len + 1, help_lang);
snprintf((char *)p + len + 1 + ML_EXTRA, STRLEN(p) + len + 1 + ML_EXTRA, "%06d",
- help_heuristic((char *)tagp.tagname,
+ help_heuristic(tagp.tagname,
match_re ? matchoff : 0, !match_no_ic)
+ help_pri);
@@ -2124,7 +2062,7 @@ parse_line:
}
get_it_again = false;
} else {
- len = (size_t)(tagp.tagname_end - tagp.tagname);
+ len = (size_t)(tagp.tagname_end - (char_u *)tagp.tagname);
mfp = xmalloc(sizeof(char) + len + 1);
STRLCPY(mfp, tagp.tagname, len + 1);
@@ -2172,7 +2110,7 @@ parse_line:
hash = hash_hash((char_u *)mfp);
}
hi = hash_lookup(&ht_match[mtt], (const char *)mfp,
- STRLEN(mfp), hash);
+ strlen(mfp), hash);
if (HASHITEM_EMPTY(hi)) {
hash_add_item(&ht_match[mtt], hi, (char_u *)mfp, hash);
ga_grow(&ga_match[mtt], 1);
@@ -2211,9 +2149,7 @@ parse_line:
sort_error = false;
}
- /*
- * Stop searching if sufficient tags have been found.
- */
+ // Stop searching if sufficient tags have been found.
if (match_count >= mincount) {
retval = OK;
stop_searching = true;
@@ -2236,7 +2172,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) {
@@ -2251,10 +2187,8 @@ findtag_end:
vim_regfree(orgpat.regmatch.regprog);
xfree(tag_fname);
- /*
- * Move the matches from the ga_match[] arrays into one list of
- * matches. When retval == FAIL, free the matches.
- */
+ // Move the matches from the ga_match[] arrays into one list of
+ // matches. When retval == FAIL, free the matches.
if (retval == FAIL) {
match_count = 0;
}
@@ -2303,19 +2237,17 @@ findtag_end:
static garray_T tag_fnames = GA_EMPTY_INIT_VALUE;
-/*
- * Callback function for finding all "tags" and "tags-??" files in
- * 'runtimepath' doc directories.
- */
+// Callback function for finding all "tags" and "tags-??" files in
+// 'runtimepath' doc directories.
static void found_tagfile_cb(char *fname, void *cookie)
{
- char_u *const tag_fname = vim_strsave((char_u *)fname);
+ char *const tag_fname = xstrdup(fname);
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(tag_fname);
#endif
- simplify_filename(tag_fname);
- GA_APPEND(char_u *, &tag_fnames, tag_fname);
+ simplify_filename((char_u *)tag_fname);
+ GA_APPEND(char *, &tag_fnames, tag_fname);
}
#if defined(EXITFREE)
@@ -2334,25 +2266,23 @@ 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);
}
if (curbuf->b_help) {
- /*
- * For help files it's done in a completely different way:
- * Find "doc/tags" and "doc/tags-??" in all directories in
- * 'runtimepath'.
- */
+ // For help files it's done in a completely different way:
+ // Find "doc/tags" and "doc/tags-??" in all directories in
+ // 'runtimepath'.
if (first) {
ga_clear_strings(&tag_fnames);
ga_init(&tag_fnames, (int)sizeof(char *), 10);
@@ -2366,16 +2296,16 @@ 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) {
+ if (strcmp(buf, ((char **)(tag_fnames.ga_data))[i]) == 0) {
return FAIL; // avoid duplicate file names
}
}
@@ -2388,24 +2318,22 @@ 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_np = (char *)tnp->tn_tags;
+ tnp->tn_tags = xstrdup((*curbuf->b_p_tags != NUL) ? curbuf->b_p_tags : (char *)p_tags);
+ tnp->tn_np = 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.
- */
+ // 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.
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;
@@ -2416,26 +2344,24 @@ int get_tagfname(tagname_T *tnp, int first, char_u *buf)
return FAIL;
}
- /*
- * Copy next file name into 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,
+ tnp->tn_search_ctx = vim_findfile_init(buf, (char *)filename,
r_ptr, 100,
- FALSE, // don't free visited list
+ false, // don't free visited list
FINDFILE_FILE, // we search for a file
- tnp->tn_search_ctx, true, (char_u *)curbuf->b_ffname);
+ tnp->tn_search_ctx, true, curbuf->b_ffname);
if (tnp->tn_search_ctx != NULL) {
- tnp->tn_did_filefind_init = TRUE;
+ tnp->tn_did_filefind_init = true;
}
}
}
@@ -2445,9 +2371,7 @@ int get_tagfname(tagname_T *tnp, int first, char_u *buf)
return OK;
}
-/*
- * Free the contents of a tagname_T that was filled by get_tagfname().
- */
+// Free the contents of a tagname_T that was filled by get_tagfname().
void tagname_free(tagname_T *tnp)
{
xfree(tnp->tn_tags);
@@ -2459,7 +2383,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
///
@@ -2469,7 +2393,7 @@ static int parse_tag_line(char_u *lbuf, tagptrs_T *tagp)
char_u *p;
// Isolate the tagname, from lbuf up to the first white
- tagp->tagname = lbuf;
+ tagp->tagname = (char *)lbuf;
p = (char_u *)vim_strchr((char *)lbuf, TAB);
if (p == NULL) {
return FAIL;
@@ -2499,20 +2423,18 @@ static int parse_tag_line(char_u *lbuf, tagptrs_T *tagp)
return OK;
}
-/*
- * Check if tagname is a static tag
- *
- * Static tags produced by the older ctags program have the format:
- * 'file:tag file /pattern'.
- * This is only recognized when both occurrence of 'file' are the same, to
- * avoid recognizing "string::string" or ":exit".
- *
- * Static tags produced by the new ctags program have the format:
- * 'tag file /pattern/;"<Tab>file:' "
- *
- * Return TRUE if it is a static tag and adjust *tagname to the real tag.
- * Return FALSE if it is not a static tag.
- */
+// Check if tagname is a static tag
+//
+// Static tags produced by the older ctags program have the format:
+// 'file:tag file /pattern'.
+// This is only recognized when both occurrence of 'file' are the same, to
+// avoid recognizing "string::string" or ":exit".
+//
+// Static tags produced by the new ctags program have the format:
+// 'tag file /pattern/;"<Tab>file:' "
+//
+// 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)
{
char_u *p;
@@ -2522,11 +2444,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.
@@ -2550,18 +2472,17 @@ static size_t matching_line_len(const char_u *const lbuf)
/// @param tagp output: pointers into the line
///
/// @return OK or FAIL.
-static int parse_match(char_u *lbuf, tagptrs_T *tagp)
+static int parse_match(char *lbuf, tagptrs_T *tagp)
{
int retval;
- char_u *p;
- char_u *pc, *pt;
+ char *p;
+ char *pc, *pt;
- tagp->tag_fname = lbuf + 1;
+ tagp->tag_fname = (char_u *)lbuf + 1;
lbuf += STRLEN(tagp->tag_fname) + 2;
// Find search pattern and the file name for non-etags.
- retval = parse_tag_line(lbuf,
- tagp);
+ retval = parse_tag_line((char_u *)lbuf, tagp);
tagp->tagkind = NULL;
tagp->user_data = NULL;
@@ -2570,32 +2491,32 @@ static int parse_match(char_u *lbuf, tagptrs_T *tagp)
if (retval == OK) {
// Try to find a kind field: "kind:<kind>" or just "<kind>"
- p = tagp->command;
- if (find_extra(&p) == OK) {
- tagp->command_end = p;
- if (p > tagp->command && p[-1] == '|') {
- tagp->command_end = p - 1; // drop trailing bar
+ p = (char *)tagp->command;
+ if (find_extra((char_u **)&p) == OK) {
+ tagp->command_end = (char_u *)p;
+ if (p > (char *)tagp->command && p[-1] == '|') {
+ tagp->command_end = (char_u *)p - 1; // drop trailing bar
}
p += 2; // skip ";\""
if (*p++ == TAB) {
// Accept ASCII alphabetic kind characters and any multi-byte
// character.
- while (ASCII_ISALPHA(*p) || utfc_ptr2len((char *)p) > 1) {
+ while (ASCII_ISALPHA(*p) || utfc_ptr2len(p) > 1) {
if (STRNCMP(p, "kind:", 5) == 0) {
- tagp->tagkind = p + 5;
+ tagp->tagkind = (char_u *)p + 5;
} else if (STRNCMP(p, "user_data:", 10) == 0) {
tagp->user_data = p + 10;
} else if (STRNCMP(p, "line:", 5) == 0) {
- tagp->tagline = atoi((char *)p + 5);
+ tagp->tagline = atoi(p + 5);
}
if (tagp->tagkind != NULL && tagp->user_data != NULL) {
break;
}
- pc = (char_u *)vim_strchr((char *)p, ':');
- pt = (char_u *)vim_strchr((char *)p, '\t');
+ pc = vim_strchr(p, ':');
+ pt = vim_strchr(p, '\t');
if (pc == NULL || (pt != NULL && pc > pt)) {
- tagp->tagkind = p;
+ tagp->tagkind = (char_u *)p;
}
if (pt == NULL) {
break;
@@ -2606,31 +2527,30 @@ static int parse_match(char_u *lbuf, tagptrs_T *tagp)
}
}
if (tagp->tagkind != NULL) {
- for (p = tagp->tagkind;
+ for (p = (char *)tagp->tagkind;
*p && *p != '\t' && *p != '\r' && *p != '\n';
MB_PTR_ADV(p)) {}
- tagp->tagkind_end = p;
+ tagp->tagkind_end = (char_u *)p;
}
if (tagp->user_data != NULL) {
for (p = tagp->user_data;
*p && *p != '\t' && *p != '\r' && *p != '\n';
MB_PTR_ADV(p)) {}
- tagp->user_data_end = p;
+ tagp->user_data_end = (char_u *)p;
}
}
return retval;
}
-/*
- * Find out the actual file name of a tag. Concatenate the tags file name
- * with the matching tag file name.
- * Returns an allocated string.
- */
+// Find out the actual file name of a tag. Concatenate the tags file name
+// with the matching tag file name.
+// Returns an allocated string.
static char_u *tag_full_fname(tagptrs_T *tagp)
{
int c = *tagp->fname_end;
*tagp->fname_end = NUL;
- char_u *fullname = expand_tag_fname(tagp->fname, tagp->tag_fname, false);
+ char_u *fullname =
+ (char_u *)expand_tag_fname((char *)tagp->fname, (char *)tagp->tag_fname, false);
*tagp->fname_end = (char_u)c;
return fullname;
@@ -2640,7 +2560,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)
@@ -2653,7 +2573,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
char_u *pbuf; // search pattern buffer
char_u *pbuf_end;
char_u *tofree_fname = NULL;
- char_u *fname;
+ char *fname;
tagptrs_T tagp;
int retval = FAIL;
int getfile_result = GETFILE_UNUSED;
@@ -2669,14 +2589,14 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
pbuf = xmalloc(LSIZE);
// parse the match line into the tagp structure
- if (parse_match(lbuf, &tagp) == FAIL) {
+ if (parse_match((char *)lbuf, &tagp) == FAIL) {
tagp.fname_end = NULL;
goto erret;
}
// truncate the file name, so it can be used as a string
*tagp.fname_end = NUL;
- fname = tagp.fname;
+ fname = (char *)tagp.fname;
// copy the command to pbuf[], remove trailing CR/NL
str = tagp.command;
@@ -2689,9 +2609,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
*pbuf_end = NUL;
{
- /*
- * Remove the "<Tab>fieldname:value" stuff; we don't need it here.
- */
+ // Remove the "<Tab>fieldname:value" stuff; we don't need it here.
str = pbuf;
if (find_extra(&str) == OK) {
pbuf_end = str;
@@ -2699,24 +2617,19 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
}
}
- /*
- * Expand file name, when needed (for environment variables).
- * If 'tagrelative' option set, may change file name.
- */
- fname = expand_tag_fname(fname, tagp.tag_fname, true);
- tofree_fname = fname; // free() it later
+ // Expand file name, when needed (for environment variables).
+ // If 'tagrelative' option set, may change file name.
+ fname = expand_tag_fname(fname, (char *)tagp.tag_fname, true);
+ tofree_fname = (char_u *)fname; // free() it later
- /*
- * Check if the file with the tag exists before abandoning the current
- * file. Also accept a file name for which there is a matching BufReadCmd
- * autocommand event (e.g., http://sys/file).
- */
+ // Check if the file with the tag exists before abandoning the current
+ // file. Also accept a file name for which there is a matching BufReadCmd
+ // autocommand event (e.g., http://sys/file).
if (!os_path_exists(fname)
- && !has_autocmd(EVENT_BUFREADCMD, (char *)fname,
- NULL)) {
+ && !has_autocmd(EVENT_BUFREADCMD, fname, NULL)) {
retval = NOTAGFILE;
xfree(nofile_fname);
- nofile_fname = vim_strsave(fname);
+ nofile_fname = xstrdup(fname);
goto erret;
}
@@ -2726,19 +2639,15 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
postponed_split = 0; // don't split again below
curwin_save = curwin; // Save current window
- /*
- * If we are reusing a window, we may change dir when
- * entering it (autocommands) so turn the tag filename
- * into a fullpath
- */
+ // If we are reusing a window, we may change dir when
+ // entering it (autocommands) so turn the tag filename
+ // into a fullpath
if (!curwin->w_p_pvw) {
- full_fname = (char_u *)FullName_save((char *)fname, FALSE);
- fname = full_fname;
+ full_fname = (char_u *)FullName_save(fname, false);
+ fname = (char *)full_fname;
- /*
- * Make the preview window the current window.
- * Open a preview window when needed.
- */
+ // Make the preview window the current window.
+ // Open a preview window when needed.
prepare_tagpreview(true);
}
}
@@ -2746,7 +2655,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
// If it was a CTRL-W CTRL-] command split window now. For ":tab tag"
// open a new tab page.
if (postponed_split && (swb_flags & (SWB_USEOPEN | SWB_USETAB))) {
- buf_T *const existing_buf = buflist_findname_exp((char *)fname);
+ buf_T *const existing_buf = buflist_findname_exp(fname);
if (existing_buf != NULL) {
const win_T *wp = NULL;
@@ -2791,7 +2700,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
if (getfile_result == GETFILE_UNUSED) {
// Careful: getfile() may trigger autocommands and call jumpto_tag()
// recursively.
- getfile_result = getfile(0, (char *)fname, NULL, true, (linenr_T)0, forceit);
+ getfile_result = getfile(0, fname, NULL, true, (linenr_T)0, forceit);
}
keep_help_flag = false;
@@ -2804,36 +2713,32 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
// Save value of no_hlsearch, jumping to a tag is not a real search
const bool save_no_hlsearch = no_hlsearch;
- /*
- * If 'cpoptions' contains 't', store the search pattern for the "n"
- * command. If 'cpoptions' does not contain 't', the search pattern
- * is not stored.
- */
+ // If 'cpoptions' contains 't', store the search pattern for the "n"
+ // command. If 'cpoptions' does not contain 't', the search pattern
+ // is not stored.
if (vim_strchr(p_cpo, CPO_TAGPAT) != NULL) {
search_options = 0;
} else {
search_options = SEARCH_KEEP;
}
- /*
- * If the command is a search, try here.
- *
- * Reset 'smartcase' for the search, since the search pattern was not
- * typed by the user.
- * Only use do_search() when there is a full search command, without
- * anything following.
- */
+ // If the command is a search, try here.
+ //
+ // Reset 'smartcase' for the search, since the search pattern was not
+ // typed by the user.
+ // Only use do_search() when there is a full search command, without
+ // anything following.
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
@@ -2849,9 +2754,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
int found = 1;
int cc;
- /*
- * try again, ignore case now
- */
+ // try again, ignore case now
p_ic = true;
if (!do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, (long)1,
search_options, NULL)) {
@@ -2876,10 +2779,8 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
emsg(_("E434: Can't find tag pattern"));
curwin->w_cursor.lnum = save_lnum;
} else {
- /*
- * Only give a message when really guessed, not when 'ic'
- * is set and match found while ignoring case.
- */
+ // Only give a message when really guessed, not when 'ic'
+ // is set and match found while ignoring case.
if (found == 2 || !save_p_ic) {
msg(_("E435: Couldn't find tag, just guessing!"));
if (!msg_scrolled && msg_silent == 0) {
@@ -2928,10 +2829,8 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
}
if (retval == OK) {
- /*
- * For a help buffer: Put the cursor line at the top of the window,
- * the help subject will be below it.
- */
+ // For a help buffer: Put the cursor line at the top of the window,
+ // the help subject will be below it.
if (curbuf->b_help) {
set_topline(curwin, curwin->w_cursor.lnum);
}
@@ -2944,7 +2843,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);
}
@@ -2967,19 +2866,18 @@ erret:
return retval;
}
-// If "expand" is true, expand wildcards in fname.
-// If 'tagrelative' option set, change fname (name of file containing tag)
-// according to tag_fname (name of tag file containing fname).
-// Returns a pointer to allocated memory.
-static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname, const bool expand)
+/// If "expand" is true, expand wildcards in fname.
+/// If 'tagrelative' option set, change fname (name of file containing tag)
+/// according to tag_fname (name of tag file containing fname).
+///
+/// @return a pointer to allocated memory.
+static char *expand_tag_fname(char *fname, char *const tag_fname, const bool expand)
{
- char_u *p;
- char_u *expanded_fname = NULL;
+ char *p;
+ char *expanded_fname = NULL;
expand_T xpc;
- /*
- * Expand file name (for environment variables) when needed.
- */
+ // Expand file name (for environment variables) when needed.
if (expand && path_has_wildcard(fname)) {
ExpandInit(&xpc);
xpc.xp_context = EXPAND_FILES;
@@ -2990,20 +2888,18 @@ static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname, const bo
}
}
- char_u *retval;
+ char *retval;
if ((p_tr || curbuf->b_help)
- && !vim_isAbsName(fname)
- && (p = (char_u *)path_tail((char *)tag_fname)) != tag_fname) {
+ && !vim_isAbsName((char_u *)fname)
+ && (p = path_tail(tag_fname)) != tag_fname) {
retval = xmalloc(MAXPATHL);
STRCPY(retval, tag_fname);
STRLCPY(retval + (p - tag_fname), fname,
MAXPATHL - (p - tag_fname));
- /*
- * Translate names like "src/a/../b/file.c" into "src/b/file.c".
- */
- simplify_filename(retval);
+ // Translate names like "src/a/../b/file.c" into "src/b/file.c".
+ simplify_filename((char_u *)retval);
} else {
- retval = vim_strsave(fname);
+ retval = xstrdup(fname);
}
xfree(expanded_fname);
@@ -3011,36 +2907,32 @@ 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 = expand_tag_fname(fname, 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;
}
-/*
- * Find the end of the tagaddress.
- * Return OK if ";\"" is following, FAIL otherwise.
- */
+// Find the end of the tagaddress.
+// Return OK if ";\"" is following, FAIL otherwise.
static int find_extra(char_u **pp)
{
char_u *str = *pp;
@@ -3051,7 +2943,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 +2999,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:
@@ -3121,8 +3013,8 @@ int expand_tags(int tagnames, char_u *pat, int *num_file, char ***file)
for (i = 0; i < *num_file; i++) {
size_t len;
- parse_match((char_u *)(*file)[i], &t_p);
- len = (size_t)(t_p.tagname_end - t_p.tagname);
+ parse_match((*file)[i], &t_p);
+ len = (size_t)(t_p.tagname_end - (char_u *)t_p.tagname);
if (len > name_buf_size - 3) {
char_u *buf;
@@ -3150,8 +3042,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;
@@ -3169,7 +3060,7 @@ static int add_tag_field(dict_T *dict, const char *field_name, const char_u *sta
char_u *buf = xmalloc(MAXPATHL);
if (start != NULL) {
if (end == NULL) {
- end = start + STRLEN(start);
+ end = start + strlen(start);
while (end > start && (end[-1] == '\r' || end[-1] == '\n')) {
end--;
}
@@ -3181,7 +3072,7 @@ static int add_tag_field(dict_T *dict, const char *field_name, const char_u *sta
STRLCPY(buf, start, len + 1);
}
buf[len] = NUL;
- retval = tv_dict_add_str(dict, field_name, STRLEN(field_name),
+ retval = tv_dict_add_str(dict, field_name, strlen(field_name),
(const char *)buf);
xfree(buf);
return retval;
@@ -3198,11 +3089,11 @@ 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);
+ int parse_result = parse_match(matches[i], &tp);
// Avoid an unused variable warning in release builds.
(void)parse_result;
@@ -3220,11 +3111,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", 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 +3150,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] = ':';
@@ -3351,9 +3242,9 @@ static void tagstack_shift(win_T *wp)
wp->w_tagstacklen--;
}
-// Push a new item to the tag stack
-static void tagstack_push_item(win_T *wp, char_u *tagname, int cur_fnum, int cur_match, pos_T mark,
- int fnum, char_u *user_data)
+/// Push a new item to the tag stack
+static void tagstack_push_item(win_T *wp, char *tagname, int cur_fnum, int cur_match, pos_T mark,
+ int fnum, char *user_data)
{
taggy_T *tagstack = wp->w_tagstack;
int idx = wp->w_tagstacklen; // top of the stack
@@ -3376,13 +3267,13 @@ static void tagstack_push_item(win_T *wp, char_u *tagname, int cur_fnum, int cur
tagstack[idx].user_data = user_data;
}
-// Add a list of items to the tag stack in the specified window
+/// Add a list of items to the tag stack in the specified window
static void tagstack_push_items(win_T *wp, list_T *l)
{
listitem_T *li;
dictitem_T *di;
dict_T *itemdict;
- char_u *tagname;
+ char *tagname;
pos_T mark;
int fnum;
@@ -3401,8 +3292,7 @@ static void tagstack_push_items(win_T *wp, list_T *l)
if (list2fpos(&di->di_tv, &mark, &fnum, NULL, false) != OK) {
continue;
}
- if ((tagname = (char_u *)tv_dict_get_string(itemdict, "tagname", true))
- == NULL) {
+ if ((tagname = tv_dict_get_string(itemdict, "tagname", true)) == NULL) {
continue;
}
@@ -3414,7 +3304,7 @@ static void tagstack_push_items(win_T *wp, list_T *l)
(int)tv_dict_get_number(itemdict, "bufnr"),
(int)tv_dict_get_number(itemdict, "matchnr") - 1,
mark, fnum,
- (char_u *)tv_dict_get_string(itemdict, "user_data", true));
+ tv_dict_get_string(itemdict, "user_data", true));
}
}
diff --git a/src/nvim/tag.h b/src/nvim/tag.h
index 0b4039afb6..7f2ef8d6d7 100644
--- a/src/nvim/tag.h
+++ b/src/nvim/tag.h
@@ -34,7 +34,7 @@
// Structure used for get_tagfname().
typedef struct {
- char_u *tn_tags; // value of 'tags' when starting
+ char *tn_tags; // value of 'tags' when starting
char *tn_np; // current position in tn_tags
int tn_did_filefind_init;
int tn_hf_idx;
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 08fcefaa88..46f141492b 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -120,6 +120,10 @@ struct terminal {
// window height has increased) and must be deleted from the terminal buffer
int sb_pending;
+ char *title; // VTermStringFragment buffer
+ size_t title_len; // number of rows pushed to sb_buffer
+ size_t title_size; // sb_buffer size
+
// buf_T instance that acts as a "drawing surface" for libvterm
// we can't store a direct reference to the buffer because the
// refresh_timer_cb may be called after the buffer was freed, and there's
@@ -230,7 +234,7 @@ Terminal *terminal_open(buf_T *buf, TerminalOptions opts)
set_option_value("wrap", false, NULL, OPT_LOCAL);
set_option_value("list", false, NULL, OPT_LOCAL);
if (buf->b_ffname != NULL) {
- buf_set_term_title(buf, buf->b_ffname);
+ buf_set_term_title(buf, buf->b_ffname, strlen(buf->b_ffname));
}
RESET_BINDING(curwin);
// Reset cursor in current window.
@@ -418,15 +422,15 @@ 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;
long save_w_p_siso = curwin->w_p_siso;
if (curwin->w_p_cul && curwin->w_p_culopt_flags & CULOPT_NBR) {
- if (STRCMP(curwin->w_p_culopt, "number")) {
+ 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 {
@@ -636,6 +640,7 @@ void terminal_destroy(Terminal **termpp)
xfree(term->sb_buffer[i]);
}
xfree(term->sb_buffer);
+ xfree(term->title);
vterm_free(term->vt);
xfree(term);
*termpp = NULL; // coverity[dead-store]
@@ -858,13 +863,13 @@ static int term_movecursor(VTermPos new, VTermPos old, int visible, void *data)
return 1;
}
-static void buf_set_term_title(buf_T *buf, char *title)
+static void buf_set_term_title(buf_T *buf, const char *title, size_t len)
FUNC_ATTR_NONNULL_ALL
{
Error err = ERROR_INIT;
dict_set_var(buf->b_vars,
STATIC_CSTR_AS_STRING("term_title"),
- STRING_OBJ(cstr_as_string(title)),
+ STRING_OBJ(((String){ .data = (char *)title, .size = len })),
false,
false,
&err);
@@ -887,7 +892,34 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data)
case VTERM_PROP_TITLE: {
buf_T *buf = handle_get_buffer(term->buf_handle);
- buf_set_term_title(buf, val->string);
+#if VTERM_VERSION_MAJOR > 0 || (VTERM_VERSION_MAJOR == 0 && VTERM_VERSION_MINOR >= 2)
+ VTermStringFragment frag = val->string;
+
+ if (frag.initial && frag.final) {
+ buf_set_term_title(buf, frag.str, frag.len);
+ break;
+ }
+
+ if (frag.initial) {
+ term->title_len = 0;
+ term->title_size = MAX(frag.len, 1024);
+ term->title = xmalloc(sizeof(char *) * term->title_size);
+ } else if (term->title_len + frag.len > term->title_size) {
+ term->title_size *= 2;
+ term->title = xrealloc(term->title, sizeof(char *) * term->title_size);
+ }
+
+ memcpy(term->title + term->title_len, frag.str, frag.len);
+ term->title_len += frag.len;
+
+ if (frag.final) {
+ buf_set_term_title(buf, term->title, term->title_len);
+ xfree(term->title);
+ term->title = NULL;
+ }
+#else
+ buf_set_term_title(buf, val->string, strlen(val->string));
+#endif
break;
}
@@ -1375,7 +1407,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 fcd3d5724c..ce23141c7a 100644
--- a/src/nvim/testdir/runtest.vim
+++ b/src/nvim/testdir/runtest.vim
@@ -114,6 +114,13 @@ if has('win32')
let $PROMPT = '$P$G'
endif
+if has('mac')
+ " In MacOS, when starting a shell in a terminal, a bash deprecation warning
+ " message is displayed. This breaks the terminal test. Disable the warning
+ " message.
+ let $BASH_SILENCE_DEPRECATION_WARNING = 1
+endif
+
" Prepare for calling test_garbagecollect_now().
let v:testing = 1
@@ -418,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
@@ -437,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
@@ -455,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 edf36b413b..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
@@ -66,8 +71,9 @@ func Test_client_server()
call remote_send(name, ":gui -f\<CR>")
endif
" Wait for the server to be up and answering requests.
- sleep 100m
- call WaitForAssert({-> assert_true(name->remote_expr("v:version", "", 1) != "")})
+ " When using valgrind this can be very, very slow.
+ sleep 1
+ call WaitForAssert({-> assert_match('\d', name->remote_expr("v:version", "", 1))}, 10000)
call remote_send(name, ":let testvar = 'maybe'\<CR>")
call WaitForAssert({-> assert_equal('maybe', remote_expr(name, "testvar", "", 2))})
@@ -178,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 35886d42c5..7443ff8fa4 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
@@ -926,6 +926,10 @@ func Test_cmdline_complete_various()
call feedkeys(":all abc\<C-A>\<C-B>\"\<CR>", 'xt')
call assert_equal("\"all abc\<C-A>", @:)
+ " completion for :wincmd with :horizontal modifier
+ call feedkeys(":horizontal wincm\<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal("\"horizontal wincmd", @:)
+
" completion for a command with a command modifier
call feedkeys(":topleft new\<C-A>\<C-B>\"\<CR>", 'xt')
call assert_equal("\"topleft new", @:)
@@ -1051,6 +1055,18 @@ func Test_cmdline_write_alternatefile()
bw!
endfunc
+func Test_cmdline_expand_cur_alt_file()
+ enew
+ file http://some.com/file.txt
+ call feedkeys(":e %\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"e http://some.com/file.txt', @:)
+ edit another
+ call feedkeys(":e #\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"e http://some.com/file.txt', @:)
+ bwipe
+ bwipe http://some.com/file.txt
+endfunc
+
" using a leading backslash here
set cpo+=C
@@ -1260,6 +1276,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 +1478,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
@@ -1809,6 +1861,36 @@ func Test_read_shellcmd()
endif
endfunc
+" Test for going up and down the directory tree using 'wildmenu'
+func Test_wildmenu_dirstack()
+ CheckUnix
+ %bw!
+ call mkdir('Xdir1/dir2/dir3', 'p')
+ call writefile([], 'Xdir1/file1_1.txt')
+ call writefile([], 'Xdir1/file1_2.txt')
+ call writefile([], 'Xdir1/dir2/file2_1.txt')
+ call writefile([], 'Xdir1/dir2/file2_2.txt')
+ call writefile([], 'Xdir1/dir2/dir3/file3_1.txt')
+ call writefile([], 'Xdir1/dir2/dir3/file3_2.txt')
+ cd Xdir1/dir2/dir3
+ set wildmenu
+
+ call feedkeys(":e \<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"e file3_1.txt', @:)
+ call feedkeys(":e \<Tab>\<Up>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"e ../dir3/', @:)
+ call feedkeys(":e \<Tab>\<Up>\<Up>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"e ../../dir2/', @:)
+ call feedkeys(":e \<Tab>\<Up>\<Up>\<Down>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"e ../../dir2/dir3/', @:)
+ call feedkeys(":e \<Tab>\<Up>\<Up>\<Down>\<Down>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"e ../../dir2/dir3/file3_1.txt', @:)
+
+ cd -
+ call delete('Xdir1', 'rf')
+ set wildmenu&
+endfunc
+
" Test for recalling newer or older cmdline from history with <Up>, <Down>,
" <S-Up>, <S-Down>, <PageUp>, <PageDown>, <C-p>, or <C-n>.
func Test_recalling_cmdline()
@@ -2129,4 +2211,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)', 'E1174:')
+ call assert_fails('call setcmdline("' .. a:text .. '", {})', 'E1210:')
+
+ 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..2e625f2388 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')
@@ -373,4 +373,26 @@ func Test_setcursorcharpos()
%bw!
endfunc
+" Test for virtcol2col()
+func Test_virtcol2col()
+ new
+ call setline(1, ["a\tb\tc"])
+ call assert_equal(1, virtcol2col(0, 1, 1))
+ call assert_equal(2, virtcol2col(0, 1, 2))
+ call assert_equal(2, virtcol2col(0, 1, 8))
+ call assert_equal(3, virtcol2col(0, 1, 9))
+ call assert_equal(4, virtcol2col(0, 1, 10))
+ call assert_equal(4, virtcol2col(0, 1, 16))
+ call assert_equal(5, virtcol2col(0, 1, 17))
+ call assert_equal(-1, virtcol2col(10, 1, 1))
+ call assert_equal(-1, virtcol2col(0, 10, 1))
+ call assert_equal(-1, virtcol2col(0, -1, 1))
+ call assert_equal(-1, virtcol2col(0, 1, -1))
+ call assert_equal(5, virtcol2col(0, 1, 20))
+ call assert_fails('echo virtcol2col("0", 1, 20)', 'E1210:')
+ call assert_fails('echo virtcol2col(0, "1", 20)', 'E1210:')
+ call assert_fails('echo virtcol2col(0, 1, "1")', 'E1210:')
+ bw!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_debugger.vim b/src/nvim/testdir/test_debugger.vim
index e038c0096a..2be94409ca 100644
--- a/src/nvim/testdir/test_debugger.vim
+++ b/src/nvim/testdir/test_debugger.vim
@@ -15,14 +15,18 @@ func CheckCWD()
endfunc
command! -nargs=0 -bar CheckCWD call CheckCWD()
+" "options" argument can contain:
+" 'msec' - time to wait for a match
+" 'match' - "pattern" to use "lines" as pattern instead of text
func CheckDbgOutput(buf, lines, options = {})
" Verify the expected output
let lnum = 20 - len(a:lines)
+ let msec = get(a:options, 'msec', 1000)
for l in a:lines
if get(a:options, 'match', 'equal') ==# 'pattern'
- call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, 200)
+ call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, msec)
else
- call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, 200)
+ call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, msec)
endif
let lnum += 1
endfor
@@ -198,7 +202,7 @@ func Test_Debugger()
" Start a debug session, so that reading the last line from the terminal
" works properly.
- call RunDbgCmd(buf, ':debug echo Foo()')
+ call RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()'])
" No breakpoints
call RunDbgCmd(buf, 'breakl', ['No breakpoints defined'])
@@ -814,9 +818,10 @@ func Test_Backtrace_CmdLine()
\ '-S Xtest1.vim -c "debug call GlobalFunction()"',
\ {'wait_for_ruler': 0})
- " Need to wait for the vim-in-terminal to be ready
+ " Need to wait for the vim-in-terminal to be ready.
+ " With valgrind this can take quite long.
call CheckDbgOutput(buf, ['command line',
- \ 'cmd: call GlobalFunction()'])
+ \ 'cmd: call GlobalFunction()'], #{msec: 5000})
" At this point the ontly thing in the stack is the cmdline
call RunDbgCmd(buf, 'backtrace', [
@@ -967,14 +972,14 @@ func Test_debug_backtrace_level()
" set a breakpoint and source file1.vim
let buf = RunVimInTerminal(
\ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim',
- \ #{ wait_for_ruler: 0 } )
+ \ #{wait_for_ruler: 0})
call CheckDbgOutput(buf, [
\ 'Breakpoint in "' .. file1 .. '" line 1',
\ 'Entering Debug mode. Type "cont" to continue.',
\ 'command line..script ' .. file1,
\ 'line 1: let s:file1_var = ''file1'''
- \ ])
+ \ ], #{msec: 5000})
" step through the initial declarations
call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] )
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_eval_stuff.vim b/src/nvim/testdir/test_eval_stuff.vim
index eff1376d3c..dc110af356 100644
--- a/src/nvim/testdir/test_eval_stuff.vim
+++ b/src/nvim/testdir/test_eval_stuff.vim
@@ -1,5 +1,8 @@
" Tests for various eval things.
+source view_util.vim
+source shared.vim
+
function s:foo() abort
try
return [] == 0
@@ -87,22 +90,47 @@ func Test_for_over_null_string()
let &enc = save_enc
endfunc
+func Test_for_invalid_line_count()
+ let lines =<< trim END
+ 111111111111111111111111 for line in ['one']
+ endfor
+ END
+ call writefile(lines, 'XinvalidFor')
+ " only test that this doesn't crash
+ call RunVim([], [], '-u NONE -e -s -S XinvalidFor -c qa')
+
+ call delete('XinvalidFor')
+endfunc
+
func Test_readfile_binary()
new
call setline(1, ['one', 'two', 'three'])
setlocal ff=dos
- silent write XReadfile
- let lines = readfile('XReadfile')
+ silent write XReadfile_bin
+ let lines = 'XReadfile_bin'->readfile()
call assert_equal(['one', 'two', 'three'], lines)
- let lines = readfile('XReadfile', '', 2)
+ let lines = readfile('XReadfile_bin', '', 2)
call assert_equal(['one', 'two'], lines)
- let lines = readfile('XReadfile', 'b')
+ let lines = readfile('XReadfile_bin', 'b')
call assert_equal(["one\r", "two\r", "three\r", ""], lines)
- let lines = readfile('XReadfile', 'b', 2)
+ let lines = readfile('XReadfile_bin', 'b', 2)
call assert_equal(["one\r", "two\r"], lines)
bwipe!
- call delete('XReadfile')
+ call delete('XReadfile_bin')
+endfunc
+
+func Test_readfile_bom()
+ call writefile(["\ufeffFOO", "FOO\ufeffBAR"], 'XReadfile_bom')
+ call assert_equal(['FOO', 'FOOBAR'], readfile('XReadfile_bom'))
+ call delete('XReadfile_bom')
+endfunc
+
+func Test_readfile_max()
+ call writefile(range(1, 4), 'XReadfile_max')
+ call assert_equal(['1', '2'], readfile('XReadfile_max', '', 2))
+ call assert_equal(['3', '4'], readfile('XReadfile_max', '', -2))
+ call delete('XReadfile_max')
endfunc
func Test_let_errmsg()
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..cf40f6211b 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -88,6 +88,7 @@ let s:filename_checks = {
\ 'bindzone': ['named.root', '/bind/db.file', '/named/db.file', 'any/bind/db.file', 'any/named/db.file'],
\ 'bitbake': ['file.bb', 'file.bbappend', 'file.bbclass', 'build/conf/local.conf', 'meta/conf/layer.conf', 'build/conf/bbappend.conf', 'meta-layer/conf/distro/foo.conf'],
\ 'blank': ['file.bl'],
+ \ 'blueprint': ['file.blp'],
\ 'bsdl': ['file.bsd', 'file.bsdl'],
\ 'bst': ['file.bst'],
\ 'bzl': ['file.bazel', 'file.bzl', 'WORKSPACE'],
@@ -209,11 +210,14 @@ 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'],
+ \ 'gitattributes': ['file.git/info/attributes', '.gitattributes', '/.config/git/attributes', '/etc/gitattributes', '/usr/local/etc/gitattributes', 'some.git/info/attributes'],
\ 'gitcommit': ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG', 'NOTES_EDITMSG', 'EDIT_DESCRIPTION'],
\ 'gitconfig': ['file.git/config', 'file.git/config.worktree', 'file.git/worktrees/x/config.worktree', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig', '/usr/local/etc/gitconfig', '/etc/gitconfig.d/file', 'any/etc/gitconfig.d/file', '/.gitconfig.d/file', 'any/.config/git/config', 'any/.gitconfig.d/file', 'some.git/config', 'some.git/modules/any/config'],
+ \ 'gitignore': ['file.git/info/exclude', '.gitignore', '/.config/git/ignore', 'some.git/info/exclude'],
\ 'gitolite': ['gitolite.conf', '/gitolite-admin/conf/file', 'any/gitolite-admin/conf/file'],
\ 'gitrebase': ['git-rebase-todo'],
\ 'gitsendemail': ['.gitsendemail.msg.xxxxxx'],
@@ -274,7 +278,7 @@ let s:filename_checks = {
\ 'jam': ['file.jpl', 'file.jpr', 'JAM-file.file', 'JAM.file', 'Prl-file.file', 'Prl.file'],
\ 'java': ['file.java', 'file.jav'],
\ 'javacc': ['file.jj', 'file.jjt'],
- \ 'javascript': ['file.js', 'file.javascript', 'file.es', 'file.mjs', 'file.cjs'],
+ \ 'javascript': ['file.js', 'file.jsm', 'file.javascript', 'file.es', 'file.mjs', 'file.cjs'],
\ 'javascript.glimmer': ['file.gjs'],
\ 'javascriptreact': ['file.jsx'],
\ 'jess': ['file.clp'],
@@ -284,6 +288,7 @@ let s:filename_checks = {
\ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.babelrc', '.eslintrc', '.prettierrc', '.firebaserc', 'file.slnf'],
\ 'json5': ['file.json5'],
\ 'jsonc': ['file.jsonc'],
+ \ 'jsonnet': ['file.jsonnet', 'file.libjsonnet'],
\ 'jsp': ['file.jsp'],
\ 'julia': ['file.jl'],
\ 'kconfig': ['Kconfig', 'Kconfig.debug', 'Kconfig.file'],
@@ -406,7 +411,7 @@ let s:filename_checks = {
\ 'perl': ['file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc'],
\ 'pf': ['pf.conf'],
\ 'pfmain': ['main.cf'],
- \ 'php': ['file.php', 'file.php9', 'file.phtml', 'file.ctp', 'file.phpt'],
+ \ 'php': ['file.php', 'file.php9', 'file.phtml', 'file.ctp', 'file.phpt', 'file.theme'],
\ 'pike': ['file.pike', 'file.pmod'],
\ 'pilrc': ['file.rcp'],
\ 'pine': ['.pinerc', 'pinerc', '.pinercex', 'pinercex'],
@@ -525,13 +530,14 @@ let s:filename_checks = {
\ 'squid': ['squid.conf'],
\ 'squirrel': ['file.nut'],
\ 'srec': ['file.s19', 'file.s28', 'file.s37', 'file.mot', 'file.srec'],
+ \ 'srt': ['file.srt'],
\ 'sshconfig': ['ssh_config', '/.ssh/config', '/etc/ssh/ssh_config.d/file.conf', 'any/etc/ssh/ssh_config.d/file.conf', 'any/.ssh/config', 'any/.ssh/file.conf'],
\ 'sshdconfig': ['sshd_config', '/etc/ssh/sshd_config.d/file.conf', 'any/etc/ssh/sshd_config.d/file.conf'],
\ 'st': ['file.st'],
\ 'stata': ['file.ado', 'file.do', 'file.imata', 'file.mata'],
\ 'stp': ['file.stp'],
\ 'sudoers': ['any/etc/sudoers', 'sudoers.tmp', '/etc/sudoers', 'any/etc/sudoers.d/file'],
- \ 'supercollider': ['file.quark'],
+ \ 'supercollider': ['file.quark'],
\ 'surface': ['file.sface'],
\ 'svelte': ['file.svelte'],
\ 'svg': ['file.svg'],
@@ -588,6 +594,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'],
@@ -1346,7 +1355,7 @@ func Test_mod_file()
unlet g:filetype_mod
bwipe!
- " RAPID header start with a line containing only "%%%",
+ " RAPID header start with a line containing only "%%%",
" but is not always present.
call writefile(['%%%'], 'modfile.mod')
split modfile.mod
@@ -1362,7 +1371,7 @@ func Test_mod_file()
bwipe!
call delete('modfile.Mod')
- " RAPID is not case sensitive, embedded spaces, sysmodule,
+ " RAPID is not case sensitive, embedded spaces, sysmodule,
" file starts with empty line(s).
call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'modfile.MOD')
split modfile.MOD
@@ -1490,7 +1499,7 @@ func Test_prg_file()
unlet g:filetype_prg
bwipe!
- " RAPID header start with a line containing only "%%%",
+ " RAPID header start with a line containing only "%%%",
" but is not always present.
call writefile(['%%%'], 'prgfile.prg')
split prgfile.prg
@@ -1506,7 +1515,7 @@ func Test_prg_file()
bwipe!
call delete('prgfile.Prg')
- " RAPID is not case sensitive, embedded spaces, sysmodule,
+ " RAPID is not case sensitive, embedded spaces, sysmodule,
" file starts with empty line(s).
call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'prgfile.PRG')
split prgfile.PRG
@@ -1617,7 +1626,7 @@ func Test_sys_file()
unlet g:filetype_sys
bwipe!
- " RAPID header start with a line containing only "%%%",
+ " RAPID header start with a line containing only "%%%",
" but is not always present.
call writefile(['%%%'], 'sysfile.sys')
split sysfile.sys
@@ -1633,7 +1642,7 @@ func Test_sys_file()
bwipe!
call delete('sysfile.Sys')
- " RAPID is not case sensitive, embedded spaces, sysmodule,
+ " RAPID is not case sensitive, embedded spaces, sysmodule,
" file starts with empty line(s).
call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'sysfile.SYS')
split sysfile.SYS
@@ -1820,6 +1829,44 @@ func Test_sig_file()
filetype off
endfunc
+" Test dist#ft#FTsil()
+func Test_sil_file()
+ filetype on
+
+ split Xfile.sil
+ call assert_equal('sil', &filetype)
+ bwipe!
+
+ let lines =<< trim END
+ // valid
+ let protoErasedPathA = \ABCProtocol.a
+
+ // also valid
+ let protoErasedPathA =
+ \ABCProtocol.a
+ END
+ call writefile(lines, 'Xfile.sil')
+
+ split Xfile.sil
+ call assert_equal('sil', &filetype)
+ bwipe!
+
+ " SILE
+
+ call writefile(['% some comment'], 'Xfile.sil')
+ split Xfile.sil
+ call assert_equal('sile', &filetype)
+ bwipe!
+
+ call writefile(['\begin[papersize=a6]{document}foo\end{document}'], 'Xfile.sil')
+ split Xfile.sil
+ call assert_equal('sile', &filetype)
+ bwipe!
+
+ call delete('Xfile.sil')
+ filetype off
+endfunc
+
func Test_inc_file()
filetype on
diff --git a/src/nvim/testdir/test_fnamemodify.vim b/src/nvim/testdir/test_fnamemodify.vim
index 5ae2a5ee17..258a2093bd 100644
--- a/src/nvim/testdir/test_fnamemodify.vim
+++ b/src/nvim/testdir/test_fnamemodify.vim
@@ -11,6 +11,7 @@ func Test_fnamemodify()
call assert_equal('/', fnamemodify('.', ':p')[-1:])
call assert_equal('r', fnamemodify('.', ':p:h')[-1:])
call assert_equal('t', fnamemodify('test.out', ':p')[-1:])
+ call assert_equal($HOME .. "/foo" , fnamemodify('~/foo', ':p'))
call assert_equal('test.out', fnamemodify('test.out', ':.'))
call assert_equal('a', fnamemodify('../testdir/a', ':.'))
call assert_equal('~/testdir/test.out', fnamemodify('test.out', ':~'))
@@ -95,4 +96,9 @@ func Test_fnamemodify_er()
call assert_equal('', fnamemodify(v:_null_string, v:_null_string))
endfunc
+func Test_fnamemodify_fail()
+ call assert_fails('call fnamemodify({}, ":p")', 'E731:')
+ call assert_fails('call fnamemodify("x", {})', 'E731:')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 44b6f0373e..c41884936e 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'))
@@ -1938,6 +2015,27 @@ func Test_getmousepos()
bwipe!
endfunc
+" Test for glob()
+func Test_glob()
+ call assert_equal('', glob(v:_null_string))
+ call assert_equal('', globpath(v:_null_string, v:_null_string))
+
+ call writefile([], 'Xglob1')
+ call writefile([], 'XGLOB2')
+ set wildignorecase
+ " Sort output of glob() otherwise we end up with different
+ " ordering depending on whether file system is case-sensitive.
+ call assert_equal(['XGLOB2', 'Xglob1'], sort(glob('Xglob[12]', 0, 1)))
+ " wildignorecase shall be applied even when the pattern contains no wildcards.
+ call assert_equal('XGLOB2', glob('xglob2'))
+ set wildignorecase&
+
+ call delete('Xglob1')
+ call delete('XGLOB2')
+
+ call assert_fails("call glob('*', 0, {})", 'E728:')
+endfunc
+
func HasDefault(msg = 'msg')
return a:msg
endfunc
diff --git a/src/nvim/testdir/test_gui.vim b/src/nvim/testdir/test_gui.vim
new file mode 100644
index 0000000000..c3f1f3163a
--- /dev/null
+++ b/src/nvim/testdir/test_gui.vim
@@ -0,0 +1,43 @@
+
+func Test_colorscheme()
+ " call assert_equal('16777216', &t_Co)
+
+ let colorscheme_saved = exists('g:colors_name') ? g:colors_name : 'default'
+ let g:color_count = 0
+ augroup TestColors
+ au!
+ au ColorScheme * let g:color_count += 1
+ \ | let g:after_colors = g:color_count
+ \ | let g:color_after = expand('<amatch>')
+ au ColorSchemePre * let g:color_count += 1
+ \ | let g:before_colors = g:color_count
+ \ | let g:color_pre = expand('<amatch>')
+ augroup END
+
+ colorscheme torte
+ redraw!
+ call assert_equal('dark', &background)
+ call assert_equal(1, g:before_colors)
+ call assert_equal(2, g:after_colors)
+ call assert_equal('torte', g:color_pre)
+ call assert_equal('torte', g:color_after)
+ call assert_equal("\ntorte", execute('colorscheme'))
+
+ let a = substitute(execute('hi Search'), "\n\\s\\+", ' ', 'g')
+ " FIXME: temporarily check less while the colorscheme changes
+ " call assert_match("\nSearch xxx term=reverse cterm=reverse ctermfg=196 ctermbg=16 gui=reverse guifg=#ff0000 guibg=#000000", a)
+ " call assert_match("\nSearch xxx term=reverse ", a)
+
+ call assert_fails('colorscheme does_not_exist', 'E185:')
+ call assert_equal('does_not_exist', g:color_pre)
+ call assert_equal('torte', g:color_after)
+
+ exec 'colorscheme' colorscheme_saved
+ augroup TestColors
+ au!
+ augroup END
+ unlet g:color_count g:after_colors g:before_colors
+ redraw!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
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..9cef6905a5 100644
--- a/src/nvim/testdir/test_listdict.vim
+++ b/src/nvim/testdir/test_listdict.vim
@@ -165,6 +165,13 @@ func Test_dict()
call assert_equal({'c': 'ccc', '1': 99, 'b': [1, 2, function('strlen')], '3': 33, '-1': {'a': 1}}, d)
call filter(d, 'v:key =~ ''[ac391]''')
call assert_equal({'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}}, d)
+
+ " allow key starting with number at the start, not a curly expression
+ call assert_equal({'1foo': 77}, #{1foo: 77})
+
+ " #{expr} is not a curly expression
+ let x = 'x'
+ call assert_equal(#{g: x}, #{g:x})
endfunc
" Dictionary identity
@@ -604,20 +611,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..f903f5b934 100644
--- a/src/nvim/testdir/test_maparg.vim
+++ b/src/nvim/testdir/test_maparg.vim
@@ -158,11 +158,11 @@ func Test_range_map()
call assert_equal("abcd", getline(1))
endfunc
-func One_mapset_test(keys)
- exe 'nnoremap ' .. a:keys .. ' original<CR>'
+func One_mapset_test(keys, rhs)
+ exe 'nnoremap ' .. a:keys .. ' ' .. a:rhs
let orig = maparg(a:keys, 'n', 0, 1)
call assert_equal(a:keys, orig.lhs)
- call assert_equal('original<CR>', orig.rhs)
+ call assert_equal(a:rhs, orig.rhs)
call assert_equal('n', orig.mode)
exe 'nunmap ' .. a:keys
@@ -172,15 +172,16 @@ func One_mapset_test(keys)
call mapset('n', 0, orig)
let d = maparg(a:keys, 'n', 0, 1)
call assert_equal(a:keys, d.lhs)
- call assert_equal('original<CR>', d.rhs)
+ call assert_equal(a:rhs, d.rhs)
call assert_equal('n', d.mode)
exe 'nunmap ' .. a:keys
endfunc
func Test_mapset()
- call One_mapset_test('K')
- call One_mapset_test('<F3>')
+ call One_mapset_test('K', 'original<CR>')
+ call One_mapset_test('<F3>', 'original<CR>')
+ call One_mapset_test('<F3>', '<lt>Nop>')
" Check <> key conversion
new
@@ -203,6 +204,26 @@ func Test_mapset()
iunmap K
+ " Test that <Nop> is restored properly
+ inoremap K <Nop>
+ call feedkeys("SK\<Esc>", 'xt')
+ call assert_equal('', getline(1))
+
+ let orig = maparg('K', 'i', 0, 1)
+ call assert_equal('K', orig.lhs)
+ call assert_equal('<Nop>', orig.rhs)
+ call assert_equal('i', orig.mode)
+
+ inoremap K foo
+ call feedkeys("SK\<Esc>", 'xt')
+ call assert_equal('foo', getline(1))
+
+ call mapset('i', 0, orig)
+ call feedkeys("SK\<Esc>", 'xt')
+ call assert_equal('', getline(1))
+
+ iunmap K
+
" Test literal <CR> using a backslash
let cpo_save = &cpo
set cpo-=B
@@ -248,6 +269,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 fdfc1c0f89..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
@@ -774,7 +780,13 @@ func Test_shell()
CheckUnix
let save_shell = &shell
set shell=
- call assert_fails('shell', 'E91:')
+ let caught_e91 = 0
+ try
+ shell
+ catch /E91:/
+ let caught_e91 = 1
+ endtry
+ call assert_equal(1, caught_e91)
let &shell = save_shell
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_profile.vim b/src/nvim/testdir/test_profile.vim
index fdb6f13e2b..4225b91bc4 100644
--- a/src/nvim/testdir/test_profile.vim
+++ b/src/nvim/testdir/test_profile.vim
@@ -40,8 +40,8 @@ func Test_profile_func()
call writefile(lines, 'Xprofile_func.vim')
call system(GetVimCommand()
\ . ' -es --clean'
- \ . ' -c "so Xprofile_func.vim"'
- \ . ' -c "qall!"')
+ \ . ' --cmd "so Xprofile_func.vim"'
+ \ . ' --cmd "qall!"')
call assert_equal(0, v:shell_error)
let lines = readfile('Xprofile_func.log')
@@ -475,7 +475,7 @@ func Test_profdel_func()
call Foo3()
[CODE]
call writefile(lines, 'Xprofile_file.vim')
- call system(GetVimCommandClean() . ' -es -c "so Xprofile_file.vim" -c q')
+ call system(GetVimCommandClean() . ' -es --cmd "so Xprofile_file.vim" --cmd q')
call assert_equal(0, v:shell_error)
let lines = readfile('Xprofile_file.log')
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_quotestar.vim b/src/nvim/testdir/test_quotestar.vim
index 93865869fa..e3ca141328 100644
--- a/src/nvim/testdir/test_quotestar.vim
+++ b/src/nvim/testdir/test_quotestar.vim
@@ -98,8 +98,6 @@ func Do_test_quotestar_for_x11()
" Running in a terminal and the GUI is available: Tell the server to open
" the GUI and check that the remote command still works.
- " Need to wait for the GUI to start up, otherwise the send hangs in trying
- " to send to the terminal window.
if has('gui_athena') || has('gui_motif')
" For those GUIs, ignore the 'failed to create input context' error.
call remote_send(name, ":call test_ignore_error('E285') | gui -f\<CR>")
@@ -107,7 +105,10 @@ func Do_test_quotestar_for_x11()
call remote_send(name, ":gui -f\<CR>")
endif
" Wait for the server in the GUI to be up and answering requests.
+ " First need to wait for the GUI to start up, otherwise the send hangs in
+ " trying to send to the terminal window.
" On some systems and with valgrind this can be very slow.
+ sleep 1
call WaitForAssert({-> assert_match("1", remote_expr(name, "has('gui_running')", "", 1))}, 10000)
call remote_send(name, ":let @* = 'maybe'\<CR>")
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_usercommands.vim b/src/nvim/testdir/test_usercommands.vim
index e37fe43b22..1065dd16e2 100644
--- a/src/nvim/testdir/test_usercommands.vim
+++ b/src/nvim/testdir/test_usercommands.vim
@@ -101,6 +101,10 @@ function Test_cmdmods()
call assert_equal('vertical', g:mods)
vert MyCmd
call assert_equal('vertical', g:mods)
+ horizontal MyCmd
+ call assert_equal('horizontal', g:mods)
+ hor MyCmd
+ call assert_equal('horizontal', g:mods)
aboveleft belowright botright browse confirm hide keepalt keepjumps
\ keepmarks keeppatterns lockmarks noautocmd noswapfile silent
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/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim
index 83a3216534..1f9d6b59b7 100644
--- a/src/nvim/testdir/test_window_cmd.vim
+++ b/src/nvim/testdir/test_window_cmd.vim
@@ -343,6 +343,46 @@ func Test_window_height()
bw Xa Xb Xc
endfunc
+func Test_wincmd_equal()
+ edit Xone
+ below split Xtwo
+ rightbelow vsplit Xthree
+ call assert_equal('Xone', bufname(winbufnr(1)))
+ call assert_equal('Xtwo', bufname(winbufnr(2)))
+ call assert_equal('Xthree', bufname(winbufnr(3)))
+
+ " Xone and Xtwo should be about the same height
+ let [wh1, wh2] = [winheight(1), winheight(2)]
+ call assert_inrange(wh1 - 1, wh1 + 1, wh2)
+ " Xtwo and Xthree should be about the same width
+ let [ww2, ww3] = [winwidth(2), winwidth(3)]
+ call assert_inrange(ww2 - 1, ww2 + 1, ww3)
+
+ 1wincmd w
+ 10wincmd _
+ 2wincmd w
+ 20wincmd |
+ call assert_equal(10, winheight(1))
+ call assert_equal(20, winwidth(2))
+
+ " equalizing horizontally doesn't change the heights
+ hor wincmd =
+ call assert_equal(10, winheight(1))
+ let [ww2, ww3] = [winwidth(2), winwidth(3)]
+ call assert_inrange(ww2 - 1, ww2 + 1, ww3)
+
+ 2wincmd w
+ 20wincmd |
+ call assert_equal(20, winwidth(2))
+ " equalizing vertically doesn't change the widths
+ vert wincmd =
+ call assert_equal(20, winwidth(2))
+ let [wh1, wh2] = [winheight(1), winheight(2)]
+ call assert_inrange(wh1 - 1, wh1 + 1, wh2)
+
+ bwipe Xone Xtwo Xthree
+endfunc
+
func Test_window_width()
e Xa
vsplit Xb
@@ -1424,4 +1464,19 @@ func Test_win_move_statusline()
%bwipe!
endfunc
+func Test_win_equal_last_status()
+ let save_lines = &lines
+ set lines=20
+ set splitbelow
+ set laststatus=0
+
+ split | split | quit
+ call assert_equal(winheight(1), winheight(2))
+
+ let &lines = save_lines
+ set splitbelow&
+ set laststatus&
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testing.c b/src/nvim/testing.c
index e70e9f2cbd..348d5c6e29 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);
}
@@ -419,7 +419,7 @@ static int assert_equalfile(typval_T *argvars)
line2[lineidx] = NUL;
ga_concat(&ga, " after \"");
ga_concat(&ga, line1);
- if (STRCMP(line1, line2) != 0) {
+ if (strcmp(line1, line2) != 0) {
ga_concat(&ga, "\" vs \"");
ga_concat(&ga, line2);
}
@@ -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..5c53f84700
--- /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 *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 = (char_u *)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 = xstrdup(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(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 = (char_u *)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 = (char_u *)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 *leader1_flags, int leader2_len,
+ char *leader2_flags)
+{
+ int idx1 = 0, idx2 = 0;
+ char *p;
+ char *line1;
+ char *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 = xstrdup(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 = (char_u *)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, (char *)leader_flags,
+ next_leader_len, (char *)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 *old;
+ char *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(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 = xstrnsave(new, (size_t)len + 2);
+ pnew[len] = ' ';
+ pnew[len + 1] = NUL;
+ ml_replace(curwin->w_cursor.lnum, 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, (char *)leader_flags,
+ next_leader_len,
+ (char *)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();
+ }
+}
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..621efa44cf
--- /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 = (char_u *)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((char *)line, (char *)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 = (char_u *)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 = (char_u *)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 = (char_u *)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 = (char_u *)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((char *)line, (char *)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 = (char_u *)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..728520c20c 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,8 +398,16 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
button = last_pressed_button;
}
- if (button == 0 || (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG
- && ev != TERMKEY_MOUSE_RELEASE)) {
+ 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_RELEASE)
+ || (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;
@@ -442,7 +453,8 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Drag");
break;
case TERMKEY_MOUSE_RELEASE:
- len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Release");
+ len += (size_t)snprintf(buf + len, sizeof(buf) - len, button ? "Release" : "MouseMove");
+ last_pressed_button = 0;
break;
case TERMKEY_MOUSE_UNKNOWN:
abort();
diff --git a/src/nvim/tui/terminfo.c b/src/nvim/tui/terminfo.c
index ce48059b94..229e340dc3 100644
--- a/src/nvim/tui/terminfo.c
+++ b/src/nvim/tui/terminfo.c
@@ -189,7 +189,7 @@ void terminfo_info_msg(const unibi_term *const ut)
msg_printf_attr(0, " %-25s %-10s = ", unibi_name_str(i),
unibi_short_name_str(i));
// Most of these strings will contain escape sequences.
- msg_outtrans_special((char_u *)s, false, 0);
+ msg_outtrans_special(s, false, 0);
msg_putchar('\n');
}
}
@@ -216,7 +216,7 @@ void terminfo_info_msg(const unibi_term *const ut)
msg_puts("Extended string capabilities:\n");
for (size_t i = 0; i < unibi_count_ext_str(ut); i++) {
msg_printf_attr(0, " %-25s = ", unibi_get_ext_str_name(ut, i));
- msg_outtrans_special((char_u *)unibi_get_ext_str(ut, i), false, 0);
+ msg_outtrans_special(unibi_get_ext_str(ut, i), false, 0);
msg_putchar('\n');
}
}
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 38e8c15762..471a3fb859 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -103,6 +103,7 @@ struct TUIData {
bool immediate_wrap_after_last_column;
bool bce;
bool mouse_enabled;
+ bool mouse_move_enabled;
bool busy, is_invisible, want_invisible;
bool cork, overflow;
bool cursor_color_changed;
@@ -117,6 +118,7 @@ struct TUIData {
ModeShape showing_mode;
struct {
int enable_mouse, disable_mouse;
+ int enable_mouse_move, disable_mouse_move;
int enable_bracketed_paste, disable_bracketed_paste;
int enable_lr_margin, disable_lr_margin;
int enter_strikethrough_mode;
@@ -236,6 +238,8 @@ static void terminfo_start(UI *ui)
data->showing_mode = SHAPE_IDX_N;
data->unibi_ext.enable_mouse = -1;
data->unibi_ext.disable_mouse = -1;
+ data->unibi_ext.enable_mouse_move = -1;
+ data->unibi_ext.disable_mouse_move = -1;
data->unibi_ext.set_cursor_color = -1;
data->unibi_ext.reset_cursor_color = -1;
data->unibi_ext.enable_bracketed_paste = -1;
@@ -1138,6 +1142,9 @@ static void tui_mouse_on(UI *ui)
TUIData *data = ui->data;
if (!data->mouse_enabled) {
unibi_out_ext(ui, data->unibi_ext.enable_mouse);
+ if (data->mouse_move_enabled) {
+ unibi_out_ext(ui, data->unibi_ext.enable_mouse_move);
+ }
data->mouse_enabled = true;
}
}
@@ -1146,6 +1153,9 @@ static void tui_mouse_off(UI *ui)
{
TUIData *data = ui->data;
if (data->mouse_enabled) {
+ if (data->mouse_move_enabled) {
+ unibi_out_ext(ui, data->unibi_ext.disable_mouse_move);
+ }
unibi_out_ext(ui, data->unibi_ext.disable_mouse);
data->mouse_enabled = false;
}
@@ -1457,9 +1467,18 @@ static void tui_screenshot(UI *ui, String path)
static void tui_option_set(UI *ui, String name, Object value)
{
TUIData *data = ui->data;
- if (strequal(name.data, "termguicolors")) {
+ if (strequal(name.data, "mousemoveevent")) {
+ if (data->mouse_move_enabled != value.data.boolean) {
+ if (data->mouse_enabled) {
+ tui_mouse_off(ui);
+ data->mouse_move_enabled = value.data.boolean;
+ tui_mouse_on(ui);
+ } else {
+ data->mouse_move_enabled = value.data.boolean;
+ }
+ }
+ } else if (strequal(name.data, "termguicolors")) {
ui->rgb = value.data.boolean;
-
data->print_attr_id = -1;
invalidate(ui, 0, data->grid.height, 0, data->grid.width);
} else if (strequal(name.data, "ttimeout")) {
@@ -2135,6 +2154,10 @@ static void augment_terminfo(TUIData *data, const char *term, long vte_version,
"\x1b[?1002h\x1b[?1006h");
data->unibi_ext.disable_mouse = (int)unibi_add_ext_str(ut, "ext.disable_mouse",
"\x1b[?1002l\x1b[?1006l");
+ data->unibi_ext.enable_mouse_move = (int)unibi_add_ext_str(ut, "ext.enable_mouse_move",
+ "\x1b[?1003h");
+ data->unibi_ext.disable_mouse_move = (int)unibi_add_ext_str(ut, "ext.disable_mouse_move",
+ "\x1b[?1003l");
// Extended underline.
// terminfo will have Smulx for this (but no support for colors yet).
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..911eefadd8 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -198,13 +198,16 @@ void ui_refresh(void)
ext_widgets[i] = true;
}
+ UI *compositor = uis[0];
+
bool inclusive = ui_override();
- for (size_t i = 0; i < ui_count; i++) {
+ for (size_t i = 1; i < ui_count; i++) {
UI *ui = uis[i];
width = MIN(ui->width, width);
height = MIN(ui->height, height);
for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
- ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
+ bool in_compositor = ui->composed && compositor->ui_ext[j];
+ ext_widgets[j] &= (ui->ui_ext[j] || in_compositor || inclusive);
}
}
@@ -336,7 +339,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 +520,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 +568,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 *p = 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..9034e7b764 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.
@@ -71,6 +69,11 @@ struct ui_t {
void (*inspect)(UI *ui, Dictionary *info);
};
+typedef struct ui_event_callback {
+ LuaRef cb;
+ bool ext_widgets[kUIGlobalCount];
+} UIEventCallback;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui.h.generated.h"
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/ui_compositor.c b/src/nvim/ui_compositor.c
index 2216e25db9..2fb70eae8a 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -20,6 +20,7 @@
#include "nvim/log.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
+#include "nvim/map.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/os/os.h"
@@ -54,6 +55,8 @@ static bool msg_was_scrolled = false;
static int msg_sep_row = -1;
static schar_T msg_sep_char = { ' ', NUL };
+static PMap(uint32_t) ui_event_cbs = MAP_INIT;
+
static int dbghl_normal, dbghl_clear, dbghl_composed, dbghl_recompose;
void ui_comp_init(void)
@@ -69,14 +72,18 @@ void ui_comp_init(void)
compositor->grid_cursor_goto = ui_comp_grid_cursor_goto;
compositor->raw_line = ui_comp_raw_line;
compositor->msg_set_pos = ui_comp_msg_set_pos;
+ compositor->event = ui_comp_event;
// Be unopinionated: will be attached together with a "real" ui anyway
compositor->width = INT_MAX;
compositor->height = INT_MAX;
- for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
+ for (UIExtension i = kUIGlobalCount; (int)i < kUIExtCount; i++) {
compositor->ui_ext[i] = true;
}
+ // TODO(bfredl): one day. in the future.
+ compositor->ui_ext[kUIMultigrid] = false;
+
// TODO(bfredl): this will be more complicated if we implement
// hlstate per UI (i e reduce hl ids for non-hlstate UIs)
compositor->ui_ext[kUIHlState] = false;
@@ -87,6 +94,15 @@ void ui_comp_init(void)
ui_attach_impl(compositor, 0);
}
+void ui_comp_free_all_mem(void)
+{
+ UIEventCallback *event_cb;
+ map_foreach_value(&ui_event_cbs, event_cb, {
+ free_ui_event_callback(event_cb);
+ })
+ pmap_destroy(uint32_t)(&ui_event_cbs);
+}
+
void ui_comp_syn_init(void)
{
dbghl_normal = syn_check_group(S_LEN("RedrawDebugNormal"));
@@ -676,3 +692,72 @@ static void ui_comp_grid_resize(UI *ui, Integer grid, Integer width, Integer hei
}
}
}
+
+static void ui_comp_event(UI *ui, char *name, Array args)
+{
+ Error err = ERROR_INIT;
+ UIEventCallback *event_cb;
+ bool handled = false;
+
+ map_foreach_value(&ui_event_cbs, event_cb, {
+ Object res = nlua_call_ref(event_cb->cb, name, args, false, &err);
+ if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
+ handled = true;
+ }
+ })
+
+ if (!handled) {
+ ui_composed_call_event(name, args);
+ }
+}
+
+static void ui_comp_update_ext(void)
+{
+ memset(compositor->ui_ext, 0, ARRAY_SIZE(compositor->ui_ext));
+
+ for (size_t i = 0; i < kUIGlobalCount; i++) {
+ UIEventCallback *event_cb;
+
+ map_foreach_value(&ui_event_cbs, event_cb, {
+ if (event_cb->ext_widgets[i]) {
+ compositor->ui_ext[i] = true;
+ break;
+ }
+ })
+ }
+}
+
+void free_ui_event_callback(UIEventCallback *event_cb)
+{
+ api_free_luaref(event_cb->cb);
+ xfree(event_cb);
+}
+
+void ui_comp_add_cb(uint32_t ns_id, LuaRef cb, bool *ext_widgets)
+{
+ UIEventCallback *event_cb = xcalloc(1, sizeof(UIEventCallback));
+ event_cb->cb = cb;
+ memcpy(event_cb->ext_widgets, ext_widgets, ARRAY_SIZE(event_cb->ext_widgets));
+ if (event_cb->ext_widgets[kUIMessages]) {
+ event_cb->ext_widgets[kUICmdline] = true;
+ }
+
+ UIEventCallback **item = (UIEventCallback **)pmap_ref(uint32_t)(&ui_event_cbs, ns_id, true);
+ if (*item) {
+ free_ui_event_callback(*item);
+ }
+ *item = event_cb;
+
+ ui_comp_update_ext();
+ ui_refresh();
+}
+
+void ui_comp_remove_cb(uint32_t ns_id)
+{
+ if (pmap_has(uint32_t)(&ui_event_cbs, ns_id)) {
+ free_ui_event_callback(pmap_get(uint32_t)(&ui_event_cbs, ns_id));
+ pmap_del(uint32_t)(&ui_event_cbs, ns_id);
+ }
+ ui_comp_update_ext();
+ ui_refresh();
+}
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 75a09b244c..891a42380e 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -621,7 +621,7 @@ void u_compute_hash(buf_T *buf, char_u *hash)
context_sha256_T ctx;
sha256_start(&ctx);
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
- char_u *p = ml_get_buf(buf, lnum, false);
+ char_u *p = (char_u *)ml_get_buf(buf, lnum, false);
sha256_update(&ctx, p, (uint32_t)(STRLEN(p) + 1));
}
sha256_finish(&ctx, hash);
@@ -651,7 +651,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
char fname_buf[MAXPATHL];
// Expand symlink in the file name, so that we put the undo file with the
// actual file instead of with the symlink.
- if (resolve_symlink((const char_u *)ffname, (char_u *)fname_buf) == OK) {
+ if (resolve_symlink(ffname, fname_buf) == OK) {
ffname = fname_buf;
}
#endif
@@ -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;
@@ -713,7 +713,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
// When reading check if the file exists.
if (undo_file_name != NULL
- && (!reading || os_path_exists((char_u *)undo_file_name))) {
+ && (!reading || os_path_exists(undo_file_name))) {
break;
}
XFREE_CLEAR(undo_file_name);
@@ -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);
@@ -1038,7 +1038,7 @@ static bool serialize_uep(bufinfo_T *bi, u_entry_T *uep)
if (!undo_write_bytes(bi, len, 4)) {
return false;
}
- if (len > 0 && !undo_write(bi, uep->ue_array[i], len)) {
+ if (len > 0 && !undo_write(bi, (char_u *)uep->ue_array[i], len)) {
return false;
}
}
@@ -1064,7 +1064,7 @@ static u_entry_T *unserialize_uep(bufinfo_T *bi, bool *error, const char *file_n
memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size);
}
}
- uep->ue_array = array;
+ uep->ue_array = (char **)array;
for (size_t i = 0; i < (size_t)uep->ue_size; i++) {
int line_len = undo_read_4c(bi);
@@ -1177,7 +1177,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
// If the undo file already exists, verify that it actually is an undo
// file, and delete it.
- if (os_path_exists((char_u *)file_name)) {
+ if (os_path_exists(file_name)) {
if (name == NULL || !forceit) {
// Check we can read it and it's an undo file.
fd = os_open(file_name, O_RDONLY, 0);
@@ -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;
@@ -2283,7 +2283,7 @@ static void u_undoredo(int undo, bool do_buf_event)
// line.
long i;
for (i = 0; i < newsize && i < oldsize; i++) {
- if (STRCMP(uep->ue_array[i], ml_get(top + 1 + (linenr_T)i)) != 0) {
+ if (strcmp(uep->ue_array[i], ml_get(top + 1 + (linenr_T)i)) != 0) {
break;
}
}
@@ -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
@@ -2327,9 +2327,9 @@ static void u_undoredo(int undo, bool do_buf_event)
// If the file is empty, there is an empty line 1 that we
// should get rid of, by replacing it with the new line
if (empty_buffer && lnum == 0) {
- ml_replace((linenr_T)1, (char *)uep->ue_array[i], true);
+ ml_replace((linenr_T)1, uep->ue_array[i], true);
} else {
- ml_append(lnum, (char *)uep->ue_array[i], (colnr_T)0, false);
+ ml_append(lnum, uep->ue_array[i], (colnr_T)0, false);
}
xfree(uep->ue_array[i]);
}
@@ -2363,7 +2363,7 @@ static void u_undoredo(int undo, bool do_buf_event)
u_newcount += newsize;
u_oldcount += oldsize;
uep->ue_size = oldsize;
- uep->ue_array = newarray;
+ uep->ue_array = (char **)newarray;
uep->ue_bot = top + newsize + 1;
// insert this entry in front of the new entry list
@@ -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);
}
}
}
@@ -2636,14 +2636,14 @@ void ex_undolist(exarg_T *eap)
if (uhp->uh_prev.ptr == NULL && uhp->uh_walk != nomark
&& uhp->uh_walk != mark) {
vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ", uhp->uh_seq, changes);
- undo_fmt_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), uhp->uh_time);
+ undo_fmt_time((char_u *)IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), uhp->uh_time);
if (uhp->uh_save_nr > 0) {
while (STRLEN(IObuff) < 33) {
STRCAT(IObuff, " ");
}
vim_snprintf_add((char *)IObuff, IOSIZE, " %3ld", uhp->uh_save_nr);
}
- GA_APPEND(char_u *, &ga, vim_strsave(IObuff));
+ GA_APPEND(char *, &ga, xstrdup((char *)IObuff));
}
uhp->uh_walk = mark;
@@ -2744,7 +2744,7 @@ void u_find_first_changed(void)
linenr_T lnum;
for (lnum = 1; lnum < curbuf->b_ml.ml_line_count
&& lnum <= uep->ue_size; lnum++) {
- if (STRCMP(ml_get_buf(curbuf, lnum, false), uep->ue_array[lnum - 1]) != 0) {
+ if (strcmp(ml_get_buf(curbuf, lnum, false), uep->ue_array[lnum - 1]) != 0) {
clearpos(&(uhp->uh_cursor));
uhp->uh_cursor.lnum = lnum;
return;
@@ -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) {
@@ -3027,16 +3027,16 @@ void u_blockfree(buf_T *buf)
/// @param lnum the line to copy
static char_u *u_save_line(linenr_T lnum)
{
- return u_save_line_buf(curbuf, lnum);
+ return (char_u *)u_save_line_buf(curbuf, lnum);
}
/// Allocate memory and copy line into it
///
/// @param lnum line to copy
/// @param buf buffer to copy from
-static char_u *u_save_line_buf(buf_T *buf, linenr_T lnum)
+static char *u_save_line_buf(buf_T *buf, linenr_T lnum)
{
- return vim_strsave(ml_get_buf(buf, lnum, false));
+ return xstrdup(ml_get_buf(buf, lnum, false));
}
/// Check if the 'modified' flag is set, or 'ff' has changed (only need to
diff --git a/src/nvim/undo_defs.h b/src/nvim/undo_defs.h
index 4b64f97919..7c065c540b 100644
--- a/src/nvim/undo_defs.h
+++ b/src/nvim/undo_defs.h
@@ -21,11 +21,11 @@ typedef struct {
typedef struct u_entry u_entry_T;
struct u_entry {
- u_entry_T *ue_next; // pointer to next entry in list
+ u_entry_T *ue_next; // pointer to next entry in list
linenr_T ue_top; // number of line above undo block
linenr_T ue_bot; // number of line below undo block
linenr_T ue_lcount; // linecount when u_save called
- char_u **ue_array; // array of lines in undo block
+ char **ue_array; // array of lines in undo block
long ue_size; // number of lines in ue_array
#ifdef U_DEBUG
int ue_magic; // magic number to check allocation
diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c
index 59b8d10200..6d6ba2466e 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,15 +272,15 @@ 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) {
+ if (strcmp(name, USER_CMD_GA(&buf->b_ucmds, i)->uc_name) == 0) {
// global command is overruled by buffer-local one
return "";
}
@@ -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;
@@ -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;
@@ -1006,7 +1006,7 @@ void ex_delcommand(exarg_T *eap)
for (;;) {
for (i = 0; i < gap->ga_len; i++) {
cmd = USER_CMD_GA(gap, i);
- res = STRCMP(arg, cmd->uc_name);
+ res = strcmp(arg, cmd->uc_name);
if (res <= 0) {
break;
}
@@ -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;
}
}
@@ -1247,6 +1247,10 @@ size_t add_win_cmd_modifers(char *buf, const cmdmod_T *cmod, bool *multi_mods)
if (cmod->cmod_split & WSP_VERT) {
result += add_cmd_modifier(buf, "vertical", multi_mods);
}
+ // :horizontal
+ if (cmod->cmod_split & WSP_HOR) {
+ result += add_cmd_modifier(buf, "horizontal", multi_mods);
+ }
return result;
}
@@ -1569,7 +1573,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..af0f231b37 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
@@ -214,7 +205,6 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext()
#define STRCPY(d, s) strcpy((char *)(d), (char *)(s))
#define STRNCPY(d, s, n) strncpy((char *)(d), (char *)(s), (size_t)(n))
#define STRLCPY(d, s, n) xstrlcpy((char *)(d), (char *)(s), (size_t)(n))
-#define STRCMP(d, s) strcmp((char *)(d), (char *)(s))
#define STRNCMP(d, s, n) strncmp((char *)(d), (char *)(s), (size_t)(n))
#ifdef HAVE_STRCASECMP
# define STRICMP(d, s) strcasecmp((char *)(d), (char *)(s))
@@ -239,11 +229,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 STRLCAT(d, s, n) xstrlcat((char *)(d), (char *)(s), (size_t)(n))
+#define STRCAT(d, s) strcat((char *)(d), (char *)(s)) // NOLINT(runtime/printf)
// Character used as separated in autoload function/variable names.
#define AUTOLOAD_CHAR '#'
@@ -258,23 +244,6 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext()
#include "nvim/path.h"
-/// Compare file names
-///
-/// On some systems case in a file name does not matter, on others it does.
-///
-/// @note Does not account for maximum name lengths and things like "../dir",
-/// thus it is not 100% accurate. OS may also use different algorithm for
-/// case-insensitive comparison.
-///
-/// @param[in] x First file name to compare.
-/// @param[in] y Second file name to compare.
-///
-/// @return 0 for equal file names, non-zero otherwise.
-#define FNAMECMP(x, y) path_fnamecmp((const char *)(x), (const char *)(y))
-#define FNAMENCMP(x, y, n) path_fnamencmp((const char *)(x), \
- (const char *)(y), \
- (size_t)(n))
-
// Enums need a typecast to be used as array index.
#define HL_ATTR(n) hl_attr_active[(int)(n)]
diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c
index 387b9d61f2..d12a690b83 100644
--- a/src/nvim/viml/parser/expressions.c
+++ b/src/nvim/viml/parser/expressions.c
@@ -66,8 +66,6 @@
#include "nvim/viml/parser/expressions.h"
#include "nvim/viml/parser/parser.h"
-#define VIM_STR2NR(s, ...) vim_str2nr((const char_u *)(s), __VA_ARGS__)
-
typedef kvec_withinit_t(ExprASTNode **, 16) ExprASTStack;
/// Which nodes may be wanted
@@ -371,7 +369,7 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
significand_part = significand_part * 10 + (pline.data[i] - '0');
}
if (exp_start) {
- VIM_STR2NR(pline.data + exp_start, NULL, NULL, 0, NULL, &exp_part,
+ vim_str2nr(pline.data + exp_start, NULL, NULL, 0, NULL, &exp_part,
(int)(ret.len - exp_start), false);
}
if (exp_negative) {
@@ -389,7 +387,7 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
} else {
int len;
int prep;
- VIM_STR2NR(pline.data, &prep, &len, STR2NR_ALL, NULL,
+ vim_str2nr(pline.data, &prep, &len, STR2NR_ALL, NULL,
&ret.data.num.val.integer, (int)pline.size, false);
ret.len = (size_t)len;
const uint8_t bases[] = {
@@ -696,8 +694,7 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags)
// Everything else is not valid.
default:
- ret.len = (size_t)utfc_ptr2len_len((const char_u *)pline.data,
- (int)pline.size);
+ ret.len = (size_t)utfc_ptr2len_len(pline.data, (int)pline.size);
ret.type = kExprLexInvalid;
ret.data.err.type = kExprLexPlainIdentifier;
ret.data.err.msg = _("E15: Unidentified character: %.*s");
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..3af024708d 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;
@@ -417,10 +417,12 @@ newwindow:
| ((nchar == 'H' || nchar == 'K') ? WSP_TOP : WSP_BOT));
break;
- // make all windows the same height
- case '=':
- win_equal(NULL, false, 'b');
+ // make all windows the same width and/or height
+ case '=': {
+ int mod = cmdmod.cmod_split & (WSP_VERT | WSP_HOR);
+ win_equal(NULL, false, mod == WSP_VERT ? 'v' : mod == WSP_HOR ? 'h' : 'b');
break;
+ }
// increase current window height
case '+':
@@ -622,12 +624,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 +714,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 +729,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 +799,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 +841,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 +930,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 {
@@ -968,21 +970,19 @@ static int check_split_disallowed(void)
return OK;
}
-/*
- * split the current window, implements CTRL-W s and :split
- *
- * "size" is the height or width for the new window, 0 to use half of current
- * height or width.
- *
- * "flags":
- * WSP_ROOM: require enough room for new window
- * WSP_VERT: vertical split.
- * WSP_TOP: open window at the top-left of the screen (help window).
- * WSP_BOT: open window at the bottom-right of the screen (quickfix window).
- * WSP_HELP: creating the help window, keep layout snapshot
- *
- * return FAIL for failure, OK otherwise
- */
+// split the current window, implements CTRL-W s and :split
+//
+// "size" is the height or width for the new window, 0 to use half of current
+// height or width.
+//
+// "flags":
+// WSP_ROOM: require enough room for new window
+// WSP_VERT: vertical split.
+// WSP_TOP: open window at the top-left of the screen (help window).
+// WSP_BOT: open window at the bottom-right of the screen (quickfix window).
+// WSP_HELP: creating the help window, keep layout snapshot
+//
+// return FAIL for failure, OK otherwise
int win_split(int size, int flags)
{
if (check_split_disallowed() == FAIL) {
@@ -1012,12 +1012,10 @@ int win_split(int size, int flags)
return win_split_ins(size, flags, NULL, 0);
}
-/*
- * When "new_wp" is NULL: split the current window in two.
- * When "new_wp" is not NULL: insert this window at the far
- * top/left/right/bottom.
- * return FAIL for failure, OK otherwise
- */
+// When "new_wp" is NULL: split the current window in two.
+// When "new_wp" is not NULL: insert this window at the far
+// top/left/right/bottom.
+// return FAIL for failure, OK otherwise
int win_split_ins(int size, int flags, win_T *new_wp, int dir)
{
win_T *wp = new_wp;
@@ -1067,10 +1065,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
layout = FR_ROW;
- /*
- * Check if we are able to split the current window and compute its
- * width.
- */
+ // Check if we are able to split the current window and compute its
+ // width.
// Current window requires at least 1 space.
wmw1 = (p_wmw == 0 ? 1 : (int)p_wmw);
needed = wmw1 + 1;
@@ -1241,9 +1237,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
}
- /*
- * allocate new window structure and link it in the window list
- */
+ // allocate new window structure and link it in the window list
if ((flags & WSP_TOP) == 0
&& ((flags & WSP_BOT)
|| (flags & WSP_BELOW)
@@ -1280,9 +1274,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
CLEAR_FIELD(wp->w_border_adj);
}
- /*
- * Reorganise the tree of frames to insert the new window.
- */
+ // Reorganise the tree of frames to insert the new window.
if (flags & (WSP_TOP | WSP_BOT)) {
if ((topframe->fr_layout == FR_COL && (flags & WSP_VERT) == 0)
|| (topframe->fr_layout == FR_ROW && (flags & WSP_VERT) != 0)) {
@@ -1299,9 +1291,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 +1466,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) {
@@ -1487,9 +1479,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
msg_col = 0; // put position back at start of line
}
- /*
- * equalize the window sizes.
- */
+ // equalize the window sizes.
if (do_equal || dir != 0) {
win_equal(wp, true, (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h') : (dir == 'h' ? 'b' : 'v'));
}
@@ -1525,13 +1515,11 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
return OK;
}
-/*
- * Initialize window "newp" from window "oldp".
- * Used when splitting a window and when creating a new tab page.
- * The windows will both edit the same buffer.
- * WSP_NEWLOC may be specified in flags to prevent the location list from
- * being copied.
- */
+// Initialize window "newp" from window "oldp".
+// Used when splitting a window and when creating a new tab page.
+// The windows will both edit the same buffer.
+// WSP_NEWLOC may be specified in flags to prevent the location list from
+// being copied.
static void win_init(win_T *newp, win_T *oldp, int flags)
{
int i;
@@ -1570,10 +1558,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;
@@ -1589,15 +1577,13 @@ static void win_init(win_T *newp, win_T *oldp, int flags)
newp->w_winbar_height = oldp->w_winbar_height;
}
-/*
- * Initialize window "newp" from window "old".
- * Only the essential things are copied.
- */
+// Initialize window "newp" from window "old".
+// Only the essential things are copied.
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
@@ -1669,9 +1655,7 @@ bool win_valid_any_tab(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
return false;
}
-/*
- * Return the number of windows.
- */
+// Return the number of windows.
int win_count(void)
{
int count = 0;
@@ -1723,7 +1707,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) {
@@ -1744,9 +1728,7 @@ int make_windows(int count, bool vertical)
return count - todo;
}
-/*
- * Exchange current and next window
- */
+// Exchange current and next window
static void win_exchange(long Prenum)
{
frame_T *frp;
@@ -1766,9 +1748,7 @@ static void win_exchange(long Prenum)
return;
}
- /*
- * find window to exchange with
- */
+ // find window to exchange with
if (Prenum) {
frp = curwin->w_frame->fr_parent->fr_child;
while (frp != NULL && --Prenum > 0) {
@@ -1787,14 +1767,12 @@ static void win_exchange(long Prenum)
}
wp = frp->fr_win;
- /*
- * 1. remove curwin from the list. Remember after which window it was in wp2
- * 2. insert curwin before wp in the list
- * if wp != wp2
- * 3. remove wp from the list
- * 4. insert wp after wp2
- * 5. exchange the status line height, winbar height, hsep height and vsep width.
- */
+ // 1. remove curwin from the list. Remember after which window it was in wp2
+ // 2. insert curwin before wp in the list
+ // if wp != wp2
+ // 3. remove wp from the list
+ // 4. insert wp after wp2
+ // 5. exchange the status line height, winbar height, hsep height and vsep width.
wp2 = curwin->w_prev;
frp2 = curwin->w_frame->fr_prev;
if (wp->w_prev != curwin) {
@@ -1837,8 +1815,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,12 +1900,10 @@ 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);
}
-/*
- * Move the current window to the very top/bottom/left/right of the screen.
- */
+// Move the current window to the very top/bottom/left/right of the screen.
static void win_totop(int size, int flags)
{
int dir = 0;
@@ -1971,10 +1947,8 @@ static void win_totop(int size, int flags)
}
}
-/*
- * Move window "win1" to below/right of "win2" and make "win1" the current
- * window. Only works within the same frame!
- */
+// Move window "win1" to below/right of "win2" and make "win1" the current
+// window. Only works within the same frame!
void win_move_after(win_T *win1, win_T *win2)
{
int height;
@@ -2034,7 +2008,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);
@@ -2074,7 +2048,7 @@ static int get_maximum_wincount(frame_T *fr, int height)
}
/// Make all windows the same height.
-///'next_curwin' will soon be the current window, make sure it has enough rows.
+/// 'next_curwin' will soon be the current window, make sure it has enough rows.
///
/// @param next_curwin pointer to current window to be or NULL
/// @param current do only frame with current window
@@ -2082,7 +2056,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 +2099,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;
@@ -2144,11 +2118,9 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
totwincount = (n + extra_sep) / ((int)p_wmw + 1);
has_next_curwin = frame_has_win(topfr, next_curwin);
- /*
- * Compute width for "next_curwin" window and room available for
- * other windows.
- * "m" is the minimal width when counting p_wiw for "next_curwin".
- */
+ // Compute width for "next_curwin" window and room available for
+ // other windows.
+ // "m" is the minimal width when counting p_wiw for "next_curwin".
m = frame_minwidth(topfr, next_curwin);
room = width - m;
if (room < 0) {
@@ -2200,7 +2172,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
}
}
@@ -2272,11 +2244,9 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
totwincount = get_maximum_wincount(topfr, n + extra_sep);
has_next_curwin = frame_has_win(topfr, next_curwin);
- /*
- * Compute height for "next_curwin" window and room available for
- * other windows.
- * "m" is the minimal height when counting p_wh for "next_curwin".
- */
+ // Compute height for "next_curwin" window and room available for
+ // other windows.
+ // "m" is the minimal height when counting p_wh for "next_curwin".
m = frame_minheight(topfr, next_curwin);
room = height - m;
if (room < 0) {
@@ -2330,7 +2300,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 +2406,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;
@@ -2592,14 +2562,12 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
free_buf = false;
}
- /*
- * Closing the last window in a tab page. First go to another tab
- * page and then close the window and the tab page. This avoids that
- * curwin and curtab are invalid while we are freeing memory, they may
- * be used in GUI events.
- * Don't trigger autocommands yet, they may use wrong values, so do
- * that below.
- */
+ // Closing the last window in a tab page. First go to another tab
+ // page and then close the window and the tab page. This avoids that
+ // curwin and curtab are invalid while we are freeing memory, they may
+ // be used in GUI events.
+ // Don't trigger autocommands yet, they may use wrong values, so do
+ // that below.
goto_tabpage_tp(alt_tabpage(), false, true);
redraw_tabline = true;
@@ -2743,10 +2711,8 @@ int win_close(win_T *win, bool free_buf, bool force)
}
}
- /*
- * Be careful: If autocommands delete the window or cause this window
- * to be the last one left, return now.
- */
+ // Be careful: If autocommands delete the window or cause this window
+ // to be the last one left, return now.
if (wp->w_buffer != curbuf) {
reset_VIsual_and_resel(); // stop Visual mode
@@ -2858,10 +2824,8 @@ int win_close(win_T *win, bool free_buf, bool force)
if (win == curwin) {
curwin = wp;
if (wp->w_p_pvw || bt_quickfix(wp->w_buffer)) {
- /*
- * If the cursor goes to the preview or the quickfix window, try
- * finding another window to go to.
- */
+ // If the cursor goes to the preview or the quickfix window, try
+ // finding another window to go to.
for (;;) {
if (wp->w_next == NULL) {
wp = firstwin;
@@ -2885,6 +2849,11 @@ int win_close(win_T *win, bool free_buf, bool force)
check_cursor();
}
+ // If last window has a status line now and we don't want one,
+ // remove the status line. Do this before win_equal(), because
+ // it may change the height of a window.
+ last_status(false);
+
if (!was_floating) {
if (!curwin->w_floating && p_ea && (*p_ead == 'b' || *p_ead == dir)) {
// If the frame of the closed window contains the new current window,
@@ -2906,12 +2875,6 @@ int win_close(win_T *win, bool free_buf, bool force)
split_disallowed--;
- /*
- * If last window has a status line now and we don't want one,
- * remove the status line.
- */
- last_status(false);
-
// After closing the help window, try restoring the window layout from
// before it was opened.
if (help_window) {
@@ -2935,7 +2898,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;
}
@@ -2953,13 +2916,11 @@ static void do_autocmd_winclosed(win_T *win)
recursive = false;
}
-/*
- * Close window "win" in tab page "tp", which is not the current tab page.
- * This may be the last window in that tab page and result in closing the tab,
- * thus "tp" may become invalid!
- * Caller must check if buffer is hidden and whether the tabline needs to be
- * updated.
- */
+// Close window "win" in tab page "tp", which is not the current tab page.
+// This may be the last window in that tab page and result in closing the tab,
+// thus "tp" may become invalid!
+// Caller must check if buffer is hidden and whether the tabline needs to be
+// updated.
void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
{
int dir;
@@ -3072,6 +3033,11 @@ static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp)
wp = firstwin;
}
}
+ xfree(win->w_float_config.title);
+ xfree(win->w_float_config.title_hl);
+ win->w_float_config.title_hl = NULL;
+ win->w_float_config.title = NULL;
+ win->w_float_config.n_title = 0;
win_free(win, tp);
// When deleting the current window of another tab page select a new
@@ -3096,7 +3062,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) {
@@ -3136,16 +3102,12 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
frame_T *frp_close = win->w_frame;
win_T *wp;
- /*
- * If there is only one window there is nothing to remove.
- */
+ // If there is only one window there is nothing to remove.
if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) {
return NULL;
}
- /*
- * Remove the window from its frame.
- */
+ // Remove the window from its frame.
frp2 = win_altframe(win, tp);
wp = frame2win(frp2);
@@ -3332,9 +3294,7 @@ static frame_T *win_altframe(win_T *win, tabpage_T *tp)
return target_fr;
}
-/*
- * Return the tabpage that will be used if the current one is closed.
- */
+// Return the tabpage that will be used if the current one is closed.
static tabpage_T *alt_tabpage(void)
{
tabpage_T *tp;
@@ -3349,9 +3309,7 @@ static tabpage_T *alt_tabpage(void)
return tp;
}
-/*
- * Find the left-upper window in frame "frp".
- */
+// Find the left-upper window in frame "frp".
win_T *frame2win(frame_T *frp)
{
while (frp->fr_win == NULL) {
@@ -3555,10 +3513,8 @@ static bool frame_fixed_width(frame_T *frp)
return true;
}
-/*
- * Add a status line to windows at the bottom of "frp".
- * Note: Does not check if there is room!
- */
+// Add a status line to windows at the bottom of "frp".
+// Note: Does not check if there is room!
static void frame_add_statusline(frame_T *frp)
{
win_T *wp;
@@ -3695,7 +3651,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;
}
@@ -3746,17 +3702,13 @@ static void frame_add_hsep(const frame_T *frp)
}
}
-/*
- * Set frame width from the window it contains.
- */
+// Set frame width from the window it contains.
static void frame_fix_width(win_T *wp)
{
wp->w_frame->fr_width = wp->w_width + wp->w_vsep_width;
}
-/*
- * Set frame height from the window it contains.
- */
+// Set frame height from the window it contains.
static void frame_fix_height(win_T *wp)
FUNC_ATTR_NONNULL_ALL
{
@@ -3911,12 +3863,10 @@ void close_others(int message, int forceit)
}
}
-/*
- * Allocate the first window and put an empty buffer in it.
- * Called from main().
- *
- * Return FAIL when something goes wrong.
- */
+// Allocate the first window and put an empty buffer in it.
+// Called from main().
+//
+// Return FAIL when something goes wrong.
int win_alloc_first(void)
{
if (win_alloc_firstwin(NULL) == FAIL) {
@@ -3947,12 +3897,10 @@ void win_alloc_aucmd_win(void)
RESET_BINDING(aucmd_win);
}
-/*
- * Allocate the first window or the first window in a new tab page.
- * When "oldwin" is NULL create an empty buffer for it.
- * When "oldwin" is not NULL copy info from it to the new window.
- * Return FAIL when something goes wrong (out of memory).
- */
+// Allocate the first window or the first window in a new tab page.
+// When "oldwin" is NULL create an empty buffer for it.
+// When "oldwin" is not NULL copy info from it to the new window.
+// Return FAIL when something goes wrong (out of memory).
static int win_alloc_firstwin(win_T *oldwin)
{
curwin = win_alloc(NULL, false);
@@ -3984,9 +3932,7 @@ static int win_alloc_firstwin(win_T *oldwin)
return OK;
}
-/*
- * Create a frame for window "wp".
- */
+// Create a frame for window "wp".
static void new_frame(win_T *wp)
{
frame_T *frp = xcalloc(1, sizeof(frame_T));
@@ -3996,9 +3942,7 @@ static void new_frame(win_T *wp)
frp->fr_win = wp;
}
-/*
- * Initialize the window and frame size to the maximum.
- */
+// Initialize the window and frame size to the maximum.
void win_init_size(void)
{
firstwin->w_height = (int)ROWS_AVAIL;
@@ -4012,9 +3956,7 @@ void win_init_size(void)
topframe->fr_width = Columns;
}
-/*
- * Allocate a new tabpage_T and init the values.
- */
+// Allocate a new tabpage_T and init the values.
static tabpage_T *alloc_tabpage(void)
{
static int last_tp_handle = 0;
@@ -4025,7 +3967,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 +3979,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 +4057,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);
@@ -4136,11 +4078,9 @@ int win_new_tabpage(int after, char_u *filename)
return FAIL;
}
-/*
- * Open a new tab page if ":tab cmd" was used. It will edit the same buffer,
- * like with ":split".
- * Returns OK if a new tab page was created, FAIL otherwise.
- */
+// Open a new tab page if ":tab cmd" was used. It will edit the same buffer,
+// like with ":split".
+// Returns OK if a new tab page was created, FAIL otherwise.
int may_open_tabpage(void)
{
int n = (cmdmod.cmod_tab == 0) ? postponed_split_tab : cmdmod.cmod_tab;
@@ -4153,10 +4093,8 @@ int may_open_tabpage(void)
return FAIL;
}
-/*
- * Create up to "maxcount" tabpages with empty windows.
- * Returns the number of resulting tab pages.
- */
+// Create up to "maxcount" tabpages with empty windows.
+// Returns the number of resulting tab pages.
int make_tabpages(int maxcount)
{
int count = maxcount;
@@ -4167,13 +4105,11 @@ int make_tabpages(int maxcount)
count = (int)p_tpm;
}
- /*
- * Don't execute autocommands while creating the tab pages. Must do that
- * when putting the buffers in the windows.
- */
+ // Don't execute autocommands while creating the tab pages. Must do that
+ // when putting the buffers in the windows.
block_autocmds();
- for (todo = count - 1; todo > 0; --todo) {
+ for (todo = count - 1; todo > 0; todo--) {
if (win_new_tabpage(0, NULL) == FAIL) {
break;
}
@@ -4237,9 +4173,7 @@ void close_tabpage(tabpage_T *tab)
free_tabpage(tab);
}
-/*
- * Find tab page "n" (first one is 1). Returns NULL when not found.
- */
+// Find tab page "n" (first one is 1). Returns NULL when not found.
tabpage_T *find_tabpage(int n)
{
tabpage_T *tp;
@@ -4251,10 +4185,8 @@ tabpage_T *find_tabpage(int n)
return tp;
}
-/*
- * Get index of tab page "tp". First one has index 1.
- * When not found returns number of tab pages plus one.
- */
+// Get index of tab page "tp". First one has index 1.
+// When not found returns number of tab pages plus one.
int tabpage_index(tabpage_T *ftp)
{
int i = 1;
@@ -4343,6 +4275,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 +4310,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
@@ -4405,10 +4342,8 @@ static void tabpage_check_windows(tabpage_T *old_curtab)
}
}
-/*
- * Go to tab page "n". For ":tab N" and "Ngt".
- * When "n" is 9999 go to the last tab page.
- */
+// Go to tab page "n". For ":tab N" and "Ngt".
+// When "n" is 9999 go to the last tab page.
void goto_tabpage(int n)
{
tabpage_T *tp = NULL; // shut up compiler
@@ -4440,7 +4375,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;
@@ -4497,10 +4432,8 @@ bool goto_tabpage_lastused(void)
return false;
}
-/*
- * Enter window "wp" in tab page "tp".
- * Also updates the GUI tab.
- */
+// Enter window "wp" in tab page "tp".
+// Also updates the GUI tab.
void goto_tabpage_win(tabpage_T *tp, win_T *wp)
{
goto_tabpage_tp(tp, true, true);
@@ -4563,13 +4496,11 @@ void tabpage_move(int nr)
redraw_tabline = true;
}
-/*
- * Go to another window.
- * When jumping to another buffer, stop Visual mode. Do this before
- * changing windows so we can yank the selection into the '*' register.
- * When jumping to another window on the same buffer, adjust its cursor
- * position to keep the same Visual area.
- */
+// Go to another window.
+// When jumping to another buffer, stop Visual mode. Do this before
+// changing windows so we can yank the selection into the '*' register.
+// When jumping to another window on the same buffer, adjust its cursor
+// position to keep the same Visual area.
void win_goto(win_T *wp)
{
win_T *owp = curwin;
@@ -4596,9 +4527,7 @@ void win_goto(win_T *wp)
}
}
-/*
- * Find the tabpage for window "win".
- */
+// Find the tabpage for window "win".
tabpage_T *win_find_tabpage(win_T *win)
{
FOR_ALL_TAB_WINDOWS(tp, wp) {
@@ -4631,10 +4560,8 @@ win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, bool up, long count)
}
while (count--) {
- /*
- * First go upwards in the tree of frames until we find an upwards or
- * downwards neighbor.
- */
+ // First go upwards in the tree of frames until we find an upwards or
+ // downwards neighbor.
fr = foundfr;
for (;;) {
if (fr == tp->tp_topframe) {
@@ -4651,9 +4578,7 @@ win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, bool up, long count)
fr = fr->fr_parent;
}
- /*
- * Now go downwards to find the bottom or top frame in it.
- */
+ // Now go downwards to find the bottom or top frame in it.
for (;;) {
if (nfr->fr_layout == FR_LEAF) {
foundfr = nfr;
@@ -4714,10 +4639,8 @@ win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, bool left, long count)
}
while (count--) {
- /*
- * First go upwards in the tree of frames until we find a left or
- * right neighbor.
- */
+ // First go upwards in the tree of frames until we find a left or
+ // right neighbor.
fr = foundfr;
for (;;) {
if (fr == tp->tp_topframe) {
@@ -4734,9 +4657,7 @@ win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, bool left, long count)
fr = fr->fr_parent;
}
- /*
- * Now go downwards to find the leftmost or rightmost frame in it.
- */
+ // Now go downwards to find the leftmost or rightmost frame in it.
for (;;) {
if (nfr->fr_layout == FR_LEAF) {
foundfr = nfr;
@@ -4836,7 +4757,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 +4788,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 +4796,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);
}
}
@@ -5029,9 +4950,7 @@ static win_T *win_alloc(win_T *after, bool hidden)
// initialized yet. gui_create_scrollbar() may trigger a FocusGained
// event.
block_autocmds();
- /*
- * link the window in the window list
- */
+ // link the window in the window list
if (!hidden) {
win_append(after, new_wp);
}
@@ -5195,9 +5114,7 @@ void win_free_grid(win_T *wp, bool reinit)
}
}
-/*
- * Append window "wp" in the window list after window "after".
- */
+// Append window "wp" in the window list after window "after".
void win_append(win_T *after, win_T *wp)
{
win_T *before;
@@ -5243,9 +5160,7 @@ void win_remove(win_T *wp, tabpage_T *tp)
}
}
-/*
- * Append frame "frp" in a frame list after frame "after".
- */
+// Append frame "frp" in a frame list after frame "after".
static void frame_append(frame_T *after, frame_T *frp)
{
frp->fr_next = after->fr_next;
@@ -5256,9 +5171,7 @@ static void frame_append(frame_T *after, frame_T *frp)
frp->fr_prev = after;
}
-/*
- * Insert frame "frp" in a frame list before frame "before".
- */
+// Insert frame "frp" in a frame list before frame "before".
static void frame_insert(frame_T *before, frame_T *frp)
{
frp->fr_next = before;
@@ -5271,9 +5184,7 @@ static void frame_insert(frame_T *before, frame_T *frp)
}
}
-/*
- * Remove a frame from a frame list.
- */
+// Remove a frame from a frame list.
static void frame_remove(frame_T *frp)
{
if (frp->fr_prev != NULL) {
@@ -5362,6 +5273,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,15 +5287,14 @@ 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;
}
}
}
-/*
- * Save the size of all windows in "gap".
- */
+// Save the size of all windows in "gap".
void win_size_save(garray_T *gap)
{
ga_init(gap, (int)sizeof(int), 1);
@@ -5450,12 +5361,10 @@ void win_reconfig_floats(void)
}
}
-/*
- * Update the position of the windows in frame "topfrp", using the width and
- * height of the frames.
- * "*row" and "*col" are the top-left position of the frame. They are updated
- * to the bottom-right position plus one.
- */
+// Update the position of the windows in frame "topfrp", using the width and
+// height of the frames.
+// "*row" and "*col" are the top-left position of the frame. They are updated
+// to the bottom-right position plus one.
static void frame_comp_pos(frame_T *topfrp, int *row, int *col)
{
win_T *wp;
@@ -5470,7 +5379,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;
}
@@ -5491,19 +5400,15 @@ static void frame_comp_pos(frame_T *topfrp, int *row, int *col)
}
}
-/*
- * Set current window height and take care of repositioning other windows to
- * fit around it.
- */
+// Set current window height and take care of repositioning other windows to
+// fit around it.
void win_setheight(int height)
{
win_setheight_win(height, curwin);
}
-/*
- * Set the window height of window "win" and take care of repositioning other
- * windows to fit around it.
- */
+// Set the window height of window "win" and take care of repositioning other
+// windows to fit around it.
void win_setheight_win(int height, win_T *win)
{
// Always keep current window at least one line high, even when 'winminheight' is zero.
@@ -5513,7 +5418,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,24 +5438,22 @@ 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;
}
}
-/*
- * Set the height of a frame to "height" and take care that all frames and
- * windows inside it are resized. Also resize frames on the left and right if
- * the are in the same FR_ROW frame.
- *
- * Strategy:
- * If the frame is part of a FR_COL frame, try fitting the frame in that
- * frame. If that doesn't work (the FR_COL frame is too small), recursively
- * go to containing frames to resize them and make room.
- * If the frame is part of a FR_ROW frame, all frames must be resized as well.
- * Check for the minimal height of the FR_ROW frame.
- * At the top level we can also use change the command line height.
- */
+// Set the height of a frame to "height" and take care that all frames and
+// windows inside it are resized. Also resize frames on the left and right if
+// the are in the same FR_ROW frame.
+//
+// Strategy:
+// If the frame is part of a FR_COL frame, try fitting the frame in that
+// frame. If that doesn't work (the FR_COL frame is too small), recursively
+// go to containing frames to resize them and make room.
+// If the frame is part of a FR_ROW frame, all frames must be resized as well.
+// Check for the minimal height of the FR_ROW frame.
+// At the top level we can also use change the command line height.
static void frame_setheight(frame_T *curfrp, int height)
{
int room; // total number of lines available
@@ -5586,17 +5489,14 @@ static void frame_setheight(frame_T *curfrp, int height)
}
frame_setheight(curfrp->fr_parent, height);
} else {
- /*
- * Column of frames: try to change only frames in this column.
- */
- /*
- * Do this twice:
- * 1: compute room available, if it's not enough try resizing the
- * containing frame.
- * 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) {
+ // Column of frames: try to change only frames in this column.
+
+ // Do this twice:
+ // 1: compute room available, if it's not enough try resizing the
+ // containing frame.
+ // 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++) {
room = 0;
room_reserved = 0;
FOR_ALL_FRAMES(frp, curfrp->fr_parent->fr_child) {
@@ -5630,13 +5530,11 @@ static void frame_setheight(frame_T *curfrp, int height)
}
frame_setheight(curfrp->fr_parent, height
+ frame_minheight(curfrp->fr_parent, NOWIN) - (int)p_wmh - 1);
- //NOTREACHED
+ // NOTREACHED
}
- /*
- * Compute the number of lines we will take from others frames (can be
- * negative!).
- */
+ // Compute the number of lines we will take from others frames (can be
+ // negative!).
take = height - curfrp->fr_height;
// If there is not enough room, also reduce the height of a window
@@ -5659,17 +5557,13 @@ static void frame_setheight(frame_T *curfrp, int height)
topframe->fr_height += room_cmdline;
}
- /*
- * set the current frame to the new height
- */
+ // set the current frame to the new height
frame_new_height(curfrp, height, false, false);
- /*
- * First take lines from the frames after the current frame. If
- * that is not enough, takes lines from frames above the current
- * frame.
- */
- for (run = 0; run < 2; ++run) {
+ // First take lines from the frames after the current frame. If
+ // that is not enough, takes lines from frames above the current
+ // frame.
+ for (run = 0; run < 2; run++) {
if (run == 0) {
frp = curfrp->fr_next; // 1st run: start with next window
} else {
@@ -5709,10 +5603,8 @@ static void frame_setheight(frame_T *curfrp, int height)
}
}
-/*
- * Set current window width and take care of repositioning other windows to
- * fit around it.
- */
+// Set current window width and take care of repositioning other windows to
+// fit around it.
void win_setwidth(int width)
{
win_setwidth_win(width, curwin);
@@ -5735,23 +5627,21 @@ 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);
}
}
-/*
- * Set the width of a frame to "width" and take care that all frames and
- * windows inside it are resized. Also resize frames above and below if the
- * are in the same FR_ROW frame.
- *
- * Strategy is similar to frame_setheight().
- */
+// Set the width of a frame to "width" and take care that all frames and
+// windows inside it are resized. Also resize frames above and below if the
+// are in the same FR_ROW frame.
+//
+// Strategy is similar to frame_setheight().
static void frame_setwidth(frame_T *curfrp, int width)
{
int room; // total number of lines available
@@ -5780,15 +5670,13 @@ static void frame_setwidth(frame_T *curfrp, int width)
}
frame_setwidth(curfrp->fr_parent, width);
} else {
- /*
- * Row of frames: try to change only frames in this row.
- *
- * Do this twice:
- * 1: compute room available, if it's not enough try resizing the
- * containing frame.
- * 2: compute the room available and adjust the width to it.
- */
- for (run = 1; run <= 2; ++run) {
+ // Row of frames: try to change only frames in this row.
+ //
+ // Do this twice:
+ // 1: compute room available, if it's not enough try resizing the
+ // containing frame.
+ // 2: compute the room available and adjust the width to it.
+ for (run = 1; run <= 2; run++) {
room = 0;
room_reserved = 0;
FOR_ALL_FRAMES(frp, curfrp->fr_parent->fr_child) {
@@ -5814,10 +5702,8 @@ static void frame_setwidth(frame_T *curfrp, int width)
+ frame_minwidth(curfrp->fr_parent, NOWIN) - (int)p_wmw - 1);
}
- /*
- * Compute the number of lines we will take from others frames (can be
- * negative!).
- */
+ // Compute the number of lines we will take from others frames (can be
+ // negative!).
take = width - curfrp->fr_width;
// If there is not enough room, also reduce the width of a window
@@ -5831,17 +5717,13 @@ static void frame_setwidth(frame_T *curfrp, int width)
room_reserved = 0;
}
- /*
- * set the current frame to the new width
- */
+ // set the current frame to the new width
frame_new_width(curfrp, width, false, false);
- /*
- * First take lines from the frames right of the current frame. If
- * that is not enough, takes lines from frames left of the current
- * frame.
- */
- for (run = 0; run < 2; ++run) {
+ // First take lines from the frames right of the current frame. If
+ // that is not enough, takes lines from frames left of the current
+ // frame.
+ for (run = 0; run < 2; run++) {
if (run == 0) {
frp = curfrp->fr_next; // 1st run: start with next window
} else {
@@ -6007,10 +5889,8 @@ void win_drag_status_line(win_T *dragwin, int offset)
return;
}
- /*
- * Grow frame fr by "offset" lines.
- * Doesn't happen when dragging the last status line up.
- */
+ // Grow frame fr by "offset" lines.
+ // Doesn't happen when dragging the last status line up.
if (fr != NULL) {
frame_new_height(fr, fr->fr_height + offset, up, false);
}
@@ -6020,9 +5900,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
} else {
fr = curfr->fr_next; // next frame gets smaller
}
- /*
- * Now make the other frames smaller.
- */
+ // Now make the other frames smaller.
while (fr != NULL && offset > 0) {
n = frame_minheight(fr, NULL);
if (fr->fr_height - offset <= n) {
@@ -6046,13 +5924,11 @@ 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();
}
-/*
- * Separator line of dragwin is dragged "offset" lines right (negative is left).
- */
+// Separator line of dragwin is dragged "offset" lines right (negative is left).
void win_drag_vsep_line(win_T *dragwin, int offset)
{
frame_T *curfr;
@@ -6153,7 +6029,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
@@ -6205,10 +6081,8 @@ void scroll_to_fraction(win_T *wp, int prev_height)
&& (!wp->w_p_scb || wp == curwin)
&& (height < wp->w_buffer->b_ml.ml_line_count
|| wp->w_topline > 1)) {
- /*
- * Find a value for w_topline that shows the cursor at the same
- * relative position in the window as before (more or less).
- */
+ // Find a value for w_topline that shows the cursor at the same
+ // relative position in the window as before (more or less).
lnum = wp->w_cursor.lnum;
if (lnum < 1) { // can happen when starting up
lnum = 1;
@@ -6228,11 +6102,9 @@ void scroll_to_fraction(win_T *wp, int prev_height)
}
if (sline < 0) {
- /*
- * Cursor line would go off top of screen if w_wrow was this high.
- * Make cursor line the first line in the window. If not enough
- * room use w_skipcol;
- */
+ // Cursor line would go off top of screen if w_wrow was this high.
+ // Make cursor line the first line in the window. If not enough
+ // room use w_skipcol;
wp->w_wrow = line_size;
if (wp->w_wrow >= wp->w_height_inner
&& (wp->w_width_inner - win_col_off(wp)) > 0) {
@@ -6264,10 +6136,8 @@ void scroll_to_fraction(win_T *wp, int prev_height)
}
if (sline < 0) {
- /*
- * Line we want at top would go off top of screen. Use next
- * line instead.
- */
+ // Line we want at top would go off top of screen. Use next
+ // line instead.
(void)hasFoldingWin(wp, lnum, NULL, &lnum, true, NULL);
lnum++;
wp->w_wrow -= line_size + sline;
@@ -6291,7 +6161,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 +6202,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 +6216,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) {
@@ -6394,9 +6264,7 @@ void win_comp_scroll(win_T *wp)
}
}
-/*
- * command_height: called whenever p_ch has been changed
- */
+// command_height: called whenever p_ch has been changed
void command_height(void)
{
int h;
@@ -6408,12 +6276,6 @@ void command_height(void)
// p_ch was changed in another tab page.
curtab->tp_ch_used = p_ch;
- // If the space for the command line is already more than 'cmdheight' there
- // is nothing to do (window size must have decreased).
- if (p_ch > old_p_ch && cmdline_row <= Rows - p_ch) {
- return;
- }
-
// If cmdline_row is smaller than what it is supposed to be for 'cmdheight'
// then set old_p_ch to what it would be, so that the windows get resized
// properly for the new value.
@@ -6479,10 +6341,8 @@ void command_height(void)
}
}
-/*
- * Resize frame "frp" to be "n" lines higher (negative for less high).
- * Also resize the frames it is contained in.
- */
+// Resize frame "frp" to be "n" lines higher (negative for less high).
+// Also resize the frames it is contained in.
static void frame_add_height(frame_T *frp, int n)
{
frame_new_height(frp, frp->fr_height + n, false, false);
@@ -6495,11 +6355,9 @@ static void frame_add_height(frame_T *frp, int n)
}
}
-/*
- * Get the file name at the cursor.
- * If Visual mode is active, use the selected text if it's in one line.
- * Returns the name in allocated memory, NULL for failure.
- */
+// Get the file name at the cursor.
+// If Visual mode is active, use the selected text if it's in one line.
+// Returns the name in allocated memory, NULL for failure.
char_u *grab_file_name(long count, linenr_T *file_lnum)
{
int options = FNAME_MESS | FNAME_EXP | FNAME_REL | FNAME_UNESC;
@@ -6515,27 +6373,25 @@ char_u *grab_file_name(long count, linenr_T *file_lnum)
*file_lnum = (linenr_T)getdigits_long(&p, false, 0);
}
- return find_file_name_in_path((char_u *)ptr, len, options, count, (char_u *)curbuf->b_ffname);
+ return (char_u *)find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname);
}
return file_name_at_cursor(options | FNAME_HYP, count, file_lnum);
}
-/*
- * Return the file name under or after the cursor.
- *
- * The 'path' option is searched if the file name is not absolute.
- * The string returned has been alloc'ed and should be freed by the caller.
- * NULL is returned if the file name or file is not found.
- *
- * options:
- * FNAME_MESS give error messages
- * FNAME_EXP expand to path
- * FNAME_HYP check for hypertext link
- * FNAME_INCL apply "includeexpr"
- */
+// Return the file name under or after the cursor.
+//
+// The 'path' option is searched if the file name is not absolute.
+// The string returned has been alloc'ed and should be freed by the caller.
+// NULL is returned if the file name or file is not found.
+//
+// options:
+// FNAME_MESS give error messages
+// FNAME_EXP expand to path
+// FNAME_HYP check for hypertext link
+// FNAME_INCL apply "includeexpr"
char_u *file_name_at_cursor(int options, long count, linenr_T *file_lnum)
{
- return file_name_in_line(get_cursor_line_ptr(),
+ return file_name_in_line((char_u *)get_cursor_line_ptr(),
curwin->w_cursor.col, options, count, (char_u *)curbuf->b_ffname,
file_lnum);
}
@@ -6552,9 +6408,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
bool in_type = true;
bool is_url = false;
- /*
- * search forward for what could be the start of a file name
- */
+ // search forward for what could be the start of a file name
ptr = (char *)line + col;
while (*ptr != NUL && !vim_isfilec(*ptr)) {
MB_PTR_ADV(ptr);
@@ -6566,12 +6420,10 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
return NULL;
}
- /*
- * Search backward for first char of the file name.
- * Go one char back to ":" before "//" even when ':' is not in 'isfname'.
- */
+ // Search backward for first char of the file name.
+ // Go one char back to ":" before "//" even when ':' is not in 'isfname'.
while ((char_u *)ptr > line) {
- if ((len = (size_t)(utf_head_off(line, (char_u *)ptr - 1))) > 0) {
+ if ((len = (size_t)(utf_head_off((char *)line, ptr - 1))) > 0) {
ptr -= len + 1;
} else if (vim_isfilec(ptr[-1]) || ((options & FNAME_HYP) && path_is_url(ptr - 1))) {
ptr--;
@@ -6580,10 +6432,8 @@ 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'.
- */
+ // Search forward for the last char of the file name.
+ // Also allow ":/" when ':' is not in 'isfname'.
len = 0;
while (vim_isfilec(ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
|| ((options & FNAME_HYP) && path_is_url(ptr + len))
@@ -6606,10 +6456,8 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
len += (size_t)(utfc_ptr2len(ptr + len));
}
- /*
- * If there is trailing punctuation, remove it.
- * But don't remove "..", could be a directory name.
- */
+ // If there is trailing punctuation, remove it.
+ // But don't remove "..", could be a directory name.
if (len > 2 && vim_strchr(".,:;!", ptr[len - 1]) != NULL
&& ptr[len - 2] != '.') {
len--;
@@ -6642,7 +6490,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
}
}
- return find_file_name_in_path((char_u *)ptr, len, options, count, rel_fname);
+ return (char_u *)find_file_name_in_path(ptr, len, options, count, (char *)rel_fname);
}
/// Add or remove a status line from window(s), according to the
@@ -6766,7 +6614,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) {
@@ -6963,21 +6811,17 @@ void reset_lnums(void)
}
}
-/*
- * A snapshot of the window sizes, to restore them after closing the help
- * window.
- * Only these fields are used:
- * fr_layout
- * fr_width
- * fr_height
- * fr_next
- * fr_child
- * fr_win (only valid for the old curwin, NULL otherwise)
- */
+// A snapshot of the window sizes, to restore them after closing the help
+// window.
+// Only these fields are used:
+// fr_layout
+// fr_width
+// fr_height
+// fr_next
+// fr_child
+// fr_win (only valid for the old curwin, NULL otherwise)
-/*
- * Create a snapshot of the current frame sizes.
- */
+// Create a snapshot of the current frame sizes.
void make_snapshot(int idx)
{
clear_snapshot(curtab, idx);
@@ -7001,9 +6845,7 @@ static void make_snapshot_rec(frame_T *fr, frame_T **frp)
}
}
-/*
- * Remove any existing snapshot.
- */
+// Remove any existing snapshot.
static void clear_snapshot(tabpage_T *tp, int idx)
{
clear_snapshot_rec(tp->tp_snapshot[idx]);
@@ -7066,7 +6908,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);
}
@@ -7088,11 +6930,9 @@ static int check_snapshot_rec(frame_T *sn, frame_T *fr)
return OK;
}
-/*
- * Copy the size of snapshot frame "sn" to frame "fr". Do the same for all
- * following frames and children.
- * Returns a pointer to the old current window, or NULL.
- */
+// Copy the size of snapshot frame "sn" to frame "fr". Do the same for all
+// following frames and children.
+// Returns a pointer to the old current window, or NULL.
static win_T *restore_snapshot_rec(frame_T *sn, frame_T *fr)
{
win_T *wp = NULL;
@@ -7291,7 +7131,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 +7229,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/src/nvim/window.h b/src/nvim/window.h
index b75b8abd9b..a564a0cfad 100644
--- a/src/nvim/window.h
+++ b/src/nvim/window.h
@@ -17,14 +17,15 @@
#define FNAME_UNESC 32 // remove backslashes used for escaping
// arguments for win_split()
-#define WSP_ROOM 1 // require enough room
-#define WSP_VERT 2 // split vertically
-#define WSP_TOP 4 // window at top-left of shell
-#define WSP_BOT 8 // window at bottom-right of shell
-#define WSP_HELP 16 // creating the help window
-#define WSP_BELOW 32 // put new window below/right
-#define WSP_ABOVE 64 // put new window above/left
-#define WSP_NEWLOC 128 // don't copy location list
+#define WSP_ROOM 0x01 // require enough room
+#define WSP_VERT 0x02 // split/equalize vertically
+#define WSP_HOR 0x04 // equalize horizontally
+#define WSP_TOP 0x08 // window at top-left of shell
+#define WSP_BOT 0x10 // window at bottom-right of shell
+#define WSP_HELP 0x20 // creating the help window
+#define WSP_BELOW 0x40 // put new window below/right
+#define WSP_ABOVE 0x80 // put new window above/left
+#define WSP_NEWLOC 0x100 // don't copy location list
// Minimum screen size
#define MIN_COLUMNS 12 // minimal columns for screen
@@ -44,8 +45,8 @@ typedef struct {
do { \
win_T *const wp_ = (wp); \
const pos_T curpos_ = wp_->w_cursor; \
- char_u cwd_[MAXPATHL]; \
- char_u autocwd_[MAXPATHL]; \
+ char cwd_[MAXPATHL]; \
+ char autocwd_[MAXPATHL]; \
bool apply_acd_ = false; \
int cwd_status_ = FAIL; \
/* Getting and setting directory can be slow on some systems, only do */ \
@@ -55,13 +56,13 @@ typedef struct {
&& (curwin->w_localdir != NULL || wp->w_localdir != NULL \
|| (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL)) \
|| p_acd)) { \
- cwd_status_ = os_dirname(cwd_, MAXPATHL); \
+ cwd_status_ = os_dirname((char_u *)cwd_, MAXPATHL); \
} \
/* If 'acd' is set, check we are using that directory. If yes, then */ \
/* apply 'acd' afterwards, otherwise restore the current directory. */ \
if (cwd_status_ == OK && p_acd) { \
do_autochdir(); \
- apply_acd_ = os_dirname(autocwd_, MAXPATHL) == OK && STRCMP(cwd_, autocwd_) == 0; \
+ apply_acd_ = os_dirname((char_u *)autocwd_, MAXPATHL) == OK && strcmp(cwd_, autocwd_) == 0; \
} \
switchwin_T switchwin_; \
if (switch_win_noblock(&switchwin_, wp_, (tp), true) == OK) { \
@@ -72,7 +73,7 @@ typedef struct {
if (apply_acd_) { \
do_autochdir(); \
} else if (cwd_status_ == OK) { \
- os_chdir((char *)cwd_); \
+ os_chdir(cwd_); \
} \
/* Update the status line if the cursor moved. */ \
if (win_valid(wp_) && !equalpos(curpos_, wp_->w_cursor)) { \
diff --git a/src/nvim/yankmap.c b/src/nvim/yankmap.c
new file mode 100644
index 0000000000..c5b8ca8838
--- /dev/null
+++ b/src/nvim/yankmap.c
@@ -0,0 +1,43 @@
+#include "nvim/yankmap.h"
+
+#include "nvim/memory.h"
+
+void init_yankmap(yankmap_T* map)
+{
+ memset(map, 0, sizeof(yankmap_T));
+
+ map_init(int, ptr_t, &map->reg_to_yankreg);
+ map_init(ptr_t, int, &map->yankreg_to_reg);
+}
+
+yankreg_T* yankmap_get(yankmap_T* yankmap, int reg)
+{
+ yankreg_T** ret =
+ (yankreg_T**) map_ref(int, ptr_t)(&yankmap->reg_to_yankreg, reg, true);
+
+ if (ret) {
+ if (! (*ret)) {
+ *ret = xcalloc(sizeof(yankreg_T), 1);
+ (*ret)->name = reg;
+ }
+
+ /* Add the back-reference */
+ int* ref = map_ref(ptr_t, int)(&yankmap->yankreg_to_reg, *ret, true);
+ *ref = reg;
+
+ return *ret;
+ }
+
+ return NULL;
+}
+
+int yankmap_find(yankmap_T* yankmap, yankreg_T* yankreg)
+{
+ int* ref = map_ref(ptr_t, int)(&yankmap->yankreg_to_reg, yankreg, false);
+
+ if (ref) {
+ return *ref;
+ }
+
+ return -1;
+}
diff --git a/src/nvim/yankmap.h b/src/nvim/yankmap.h
new file mode 100644
index 0000000000..da7c4dcf13
--- /dev/null
+++ b/src/nvim/yankmap.h
@@ -0,0 +1,24 @@
+#ifndef YANK_TRIE_H_
+#define YANK_TRIE_H_
+
+#include <stdbool.h>
+#include "nvim/ops.h"
+#include "nvim/map.h"
+
+typedef struct {
+ /* Register name to yank register. */
+ Map(int, ptr_t) reg_to_yankreg;
+
+ /* Yank register to register name. */
+ Map(ptr_t, int) yankreg_to_reg;
+} yankmap_T;
+
+void init_yankmap(yankmap_T* yankmap);
+
+yankreg_T* yankmap_get(yankmap_T* yankmap, int index);
+
+yankreg_T* yankmap_put(yankmap_T* yankmap, int index);
+
+int yankmap_find(yankmap_T* yankmap, yankreg_T* yankreg);
+
+#endif
diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua
index 890710b6e6..44a19d8348 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,
@@ -125,6 +125,7 @@ describe('nvim_create_user_command', function()
confirm = false,
emsg_silent = false,
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -135,7 +136,7 @@ describe('nvim_create_user_command', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -144,7 +145,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
]=])
@@ -160,6 +161,7 @@ describe('nvim_create_user_command', function()
confirm = false,
emsg_silent = false,
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -170,7 +172,7 @@ describe('nvim_create_user_command', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -195,6 +197,7 @@ describe('nvim_create_user_command', function()
confirm = false,
emsg_silent = false,
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -205,7 +208,7 @@ describe('nvim_create_user_command', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -224,12 +227,13 @@ describe('nvim_create_user_command', function()
bang = true,
line1 = 10,
line2 = 10,
- mods = "confirm unsilent botright",
+ mods = "confirm unsilent botright horizontal",
smods = {
browse = false,
confirm = true,
emsg_silent = false,
hide = false,
+ horizontal = true,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -240,7 +244,7 @@ describe('nvim_create_user_command', function()
sandbox = false,
silent = false,
split = "botright",
- tab = 0,
+ tab = -1,
unsilent = true,
verbose = -1,
vertical = false,
@@ -249,7 +253,7 @@ describe('nvim_create_user_command', function()
count = 10,
reg = "",
}, exec_lua [=[
- vim.api.nvim_command('unsilent botright confirm 10CommandWithLuaCallback! h\tey ')
+ vim.api.nvim_command('unsilent horizontal botright confirm 10CommandWithLuaCallback! h\tey ')
return result
]=])
@@ -265,6 +269,7 @@ describe('nvim_create_user_command', function()
confirm = false,
emsg_silent = false,
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -275,7 +280,7 @@ describe('nvim_create_user_command', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -300,6 +305,7 @@ describe('nvim_create_user_command', function()
confirm = false,
emsg_silent = false,
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -310,7 +316,7 @@ describe('nvim_create_user_command', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -347,6 +353,7 @@ describe('nvim_create_user_command', function()
confirm = false,
emsg_silent = false,
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -357,7 +364,7 @@ describe('nvim_create_user_command', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -383,6 +390,7 @@ describe('nvim_create_user_command', function()
confirm = false,
emsg_silent = false,
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -393,7 +401,7 @@ describe('nvim_create_user_command', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -429,6 +437,7 @@ describe('nvim_create_user_command', function()
confirm = false,
emsg_silent = false,
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -439,7 +448,7 @@ describe('nvim_create_user_command', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -514,8 +523,29 @@ describe('nvim_create_user_command', function()
vim.api.nvim_cmd({ cmd = 'echo', args = { '&verbose' }, mods = opts.smods }, {})
end, {})
]]
-
eq("3", meths.cmd({ cmd = 'MyEcho', mods = { verbose = 3 } }, { output = true }))
+
+ eq(1, #meths.list_tabpages())
+ exec_lua[[
+ vim.api.nvim_create_user_command('MySplit', function(opts)
+ vim.api.nvim_cmd({ cmd = 'split', mods = opts.smods }, {})
+ end, {})
+ ]]
+ meths.cmd({ cmd = 'MySplit' }, {})
+ eq(1, #meths.list_tabpages())
+ eq(2, #meths.list_wins())
+ meths.cmd({ cmd = 'MySplit', mods = { tab = 1 } }, {})
+ eq(2, #meths.list_tabpages())
+ eq(2, funcs.tabpagenr())
+ meths.cmd({ cmd = 'MySplit', mods = { tab = 1 } }, {})
+ eq(3, #meths.list_tabpages())
+ eq(2, funcs.tabpagenr())
+ meths.cmd({ cmd = 'MySplit', mods = { tab = 3 } }, {})
+ eq(4, #meths.list_tabpages())
+ eq(4, funcs.tabpagenr())
+ meths.cmd({ cmd = 'MySplit', mods = { tab = 0 } }, {})
+ eq(5, #meths.list_tabpages())
+ eq(1, funcs.tabpagenr())
end)
end)
diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua
index 2730f7e23d..3b36563d21 100644
--- a/test/functional/api/highlight_spec.lua
+++ b/test/functional/api/highlight_spec.lua
@@ -354,4 +354,9 @@ describe("API: set highlight", function()
meths.set_hl(0, 'Normal', {fg='#000083', bg='#0000F3'})
eq({foreground = 131, background = 243}, nvim("get_hl_by_name", 'Normal', true))
end)
+
+ it('does not segfault on invalid group name #20009', function()
+ eq('Invalid highlight name: foo bar', pcall_err(meths.set_hl, 0, 'foo bar', {bold = true}))
+ assert_alive()
+ end)
end)
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index a93a4544ff..fedcbfa76a 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -6,6 +6,7 @@ local command = helpers.command
local curbufmeths = helpers.curbufmeths
local eq, neq = helpers.eq, helpers.neq
local exec_lua = helpers.exec_lua
+local exec = helpers.exec
local feed = helpers.feed
local funcs = helpers.funcs
local meths = helpers.meths
@@ -336,21 +337,26 @@ describe('nvim_get_keymap', function()
end)
it('can handle lua mappings', function()
- eq(0, exec_lua [[
+ eq(0, exec_lua([[
GlobalCount = 0
- vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]])
+ ]]))
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua([[return GlobalCount]]))
- eq(2, exec_lua[[
+ eq(2, exec_lua([[
vim.api.nvim_get_keymap('n')[1].callback()
return GlobalCount
+ ]]))
+
+ exec([[
+ call nvim_get_keymap('n')[0].callback()
]])
+ eq(3, exec_lua([[return GlobalCount]]))
+
local mapargs = meths.get_keymap('n')
- assert(type(mapargs[1].callback) == 'number', 'callback is not luaref number')
mapargs[1].callback = nil
eq({
lhs='asdf',
@@ -834,17 +840,29 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
end)
it ('maparg() returns lua mapping correctly', function()
- exec_lua [[
- vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() print('jkl;') end })
- ]]
- assert.truthy(string.match(funcs.maparg('asdf', 'n'),
- "^<Lua %d+>"))
+ eq(0, exec_lua([[
+ GlobalCount = 0
+ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ return GlobalCount
+ ]]))
+
+ assert.truthy(string.match(funcs.maparg('asdf', 'n'), "^<Lua %d+>"))
+
local mapargs = funcs.maparg('asdf', 'n', false, true)
- assert(type(mapargs.callback) == 'number', 'callback is not luaref number')
mapargs.callback = nil
mapargs.lhsraw = nil
mapargs.lhsrawalt = nil
eq(generate_mapargs('n', 'asdf', nil, {sid=sid_lua}), mapargs)
+
+ eq(1, exec_lua([[
+ vim.fn.maparg('asdf', 'n', false, true).callback()
+ return GlobalCount
+ ]]))
+
+ exec([[
+ call maparg('asdf', 'n', v:false, v:true).callback()
+ ]])
+ eq(2, exec_lua([[return GlobalCount]]))
end)
it('can make lua expr mappings replacing keycodes', function()
diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua
index 1c00f001ff..1c554b05a3 100644
--- a/test/functional/api/server_notifications_spec.lua
+++ b/test/functional/api/server_notifications_spec.lua
@@ -7,6 +7,7 @@ local exec_lua = helpers.exec_lua
local retry = helpers.retry
local isCI = helpers.isCI
local assert_alive = helpers.assert_alive
+local uname = helpers.uname
describe('notify', function()
local channel
@@ -78,6 +79,9 @@ describe('notify', function()
end)
it('cancels stale events on channel close', function()
+ if uname() == 'freebsd' then
+ pending('Failing FreeBSD test')
+ end
if isCI() then
pending('hangs on CI #14083 #15251')
return
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 72a03c409a..44775ef85c 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -2732,8 +2732,8 @@ describe('API', function()
it('should have information about window options', function()
eq({
- allows_duplicates = true,
- commalist = false;
+ allows_duplicates = false,
+ commalist = true;
default = "";
flaglist = false;
global_local = false;
@@ -3195,6 +3195,7 @@ describe('API', function()
force = false
},
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3205,7 +3206,7 @@ describe('API', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -3236,6 +3237,7 @@ describe('API', function()
force = false
},
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3246,7 +3248,7 @@ describe('API', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -3277,6 +3279,7 @@ describe('API', function()
force = false
},
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3287,7 +3290,7 @@ describe('API', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -3318,6 +3321,7 @@ describe('API', function()
force = false
},
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3328,7 +3332,7 @@ describe('API', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -3359,6 +3363,7 @@ describe('API', function()
force = false
},
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3369,7 +3374,7 @@ describe('API', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -3400,6 +3405,7 @@ describe('API', function()
force = false
},
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3410,7 +3416,7 @@ describe('API', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -3441,6 +3447,7 @@ describe('API', function()
force = false
},
hide = false,
+ horizontal = true,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3451,12 +3458,12 @@ describe('API', function()
sandbox = false,
silent = true,
split = "topleft",
- tab = 2,
+ tab = 1,
unsilent = false,
verbose = 15,
vertical = false,
},
- }, meths.parse_cmd('15verbose silent! aboveleft topleft tab filter /foo/ split foo.txt', {}))
+ }, meths.parse_cmd('15verbose silent! horizontal topleft tab filter /foo/ split foo.txt', {}))
eq({
cmd = 'split',
args = { 'foo.txt' },
@@ -3480,6 +3487,7 @@ describe('API', function()
force = true
},
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3495,7 +3503,7 @@ describe('API', function()
verbose = 0,
vertical = false,
},
- }, meths.parse_cmd('0verbose unsilent botright confirm filter! /foo/ split foo.txt', {}))
+ }, meths.parse_cmd('0verbose unsilent botright 0tab confirm filter! /foo/ split foo.txt', {}))
end)
it('works with user commands', function()
command('command -bang -nargs=+ -range -addr=lines MyCommand echo foo')
@@ -3522,6 +3530,7 @@ describe('API', function()
force = false
},
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3532,7 +3541,7 @@ describe('API', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -3563,6 +3572,7 @@ describe('API', function()
force = false
},
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3573,7 +3583,7 @@ describe('API', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -3605,6 +3615,7 @@ describe('API', function()
force = false
},
hide = false,
+ horizontal = false,
keepalt = false,
keepjumps = false,
keepmarks = false,
@@ -3615,7 +3626,7 @@ describe('API', function()
sandbox = false,
silent = false,
split = "",
- tab = 0,
+ tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
@@ -3668,6 +3679,56 @@ 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,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = "",
+ tab = -1,
+ 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 ()
@@ -3749,10 +3810,20 @@ describe('API', function()
eq('1',
meths.cmd({ cmd = 'echomsg', args = { '1' }, mods = { silent = true } },
{ output = true }))
- -- with :silent message isn't added to message history
+ -- but message isn't added to message history
eq('', meths.cmd({ cmd = 'messages' }, { output = true }))
meths.create_user_command("Foo", 'set verbose', {})
eq(" verbose=1", meths.cmd({ cmd = "Foo", mods = { verbose = 1 } }, { output = true }))
+ meths.create_user_command("Mods", "echo '<mods>'", {})
+ eq('keepmarks keeppatterns silent 3verbose aboveleft horizontal',
+ meths.cmd({ cmd = "Mods", mods = {
+ horizontal = true,
+ keepmarks = true,
+ keeppatterns = true,
+ silent = true,
+ split = 'aboveleft',
+ verbose = 3,
+ } }, { output = true }))
eq(0, meths.get_option_value("verbose", {}))
command('edit foo.txt | edit bar.txt')
eq(' 1 #h "foo.txt" line 1',
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/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua
index a4d22685e8..e71131dcf8 100644
--- a/test/functional/core/fileio_spec.lua
+++ b/test/functional/core/fileio_spec.lua
@@ -23,6 +23,7 @@ local iswin = helpers.iswin
local assert_alive = helpers.assert_alive
local expect_exit = helpers.expect_exit
local write_file = helpers.write_file
+local uname = helpers.uname
describe('fileio', function()
before_each(function()
@@ -83,6 +84,9 @@ describe('fileio', function()
end)
it('backup #9709', function()
+ if uname() == 'freebsd' then
+ pending('Failing FreeBSD test')
+ end
clear({ args={ '-i', 'Xtest_startup_shada',
'--cmd', 'set directory=Xtest_startup_swapdir' } })
@@ -102,6 +106,9 @@ describe('fileio', function()
end)
it('backup with full path #11214', function()
+ if uname() == 'freebsd' then
+ pending('Failing FreeBSD test')
+ end
clear()
mkdir('Xtest_backupdir')
command('set backup')
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..10ebefd8cd 100644
--- a/test/functional/ex_cmds/source_spec.lua
+++ b/test/functional/ex_cmds/source_spec.lua
@@ -104,7 +104,7 @@ describe(':source', function()
eq("0zBEEFCAFE", meths.exec('echo d', true))
exec('set cpoptions+=C')
- eq('Vim(let):E15: Invalid expression: #{', exc_exec('source'))
+ eq('Vim(let):E723: Missing end of Dictionary \'}\': ', exc_exec('source'))
end)
it('selection in current buffer', function()
@@ -138,7 +138,7 @@ describe(':source', function()
eq('Vim(echo):E117: Unknown function: s:C', exc_exec('echo D()'))
exec('set cpoptions+=C')
- eq('Vim(let):E15: Invalid expression: #{', exc_exec("'<,'>source"))
+ eq('Vim(let):E723: Missing end of Dictionary \'}\': ', exc_exec("'<,'>source"))
end)
it('does not break if current buffer is modified while sourced', function()
@@ -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/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua
index 32fe397c03..14035a4341 100644
--- a/test/functional/ex_cmds/write_spec.lua
+++ b/test/functional/ex_cmds/write_spec.lua
@@ -9,6 +9,7 @@ local feed_command = helpers.feed_command
local funcs = helpers.funcs
local meths = helpers.meths
local iswin = helpers.iswin
+local uname = helpers.uname
local fname = 'Xtest-functional-ex_cmds-write'
local fname_bak = fname .. '~'
@@ -52,6 +53,9 @@ describe(':write', function()
end)
it('&backupcopy=no replaces symlink with new file', function()
+ if uname() == 'freebsd' then
+ pending('Failing FreeBSD test')
+ end
command('set backupcopy=no')
write_file('test_bkc_file.txt', 'content0')
if iswin() then
@@ -91,6 +95,9 @@ describe(':write', function()
end)
it('errors out correctly', function()
+ if uname() == 'freebsd' then
+ pending('Failing FreeBSD test')
+ end
command('let $HOME=""')
eq(funcs.fnamemodify('.', ':p:h'), funcs.fnamemodify('.', ':p:h:~'))
-- Message from check_overwrite
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 981cfc306e..d672037a1e 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -755,15 +755,6 @@ function module.pending_win32(pending_fn)
end
end
-function module.pending_c_parser(pending_fn)
- local status, _ = unpack(module.exec_lua([[ return {pcall(vim.treesitter.require_language, 'c')} ]]))
- if not status then
- pending_fn 'no C parser, skipping'
- return true
- end
- return false
-end
-
-- Calls pending() and returns `true` if the system is too slow to
-- run fragile or expensive tests. Else returns `false`.
function module.skip_fragile(pending_fn, cond)
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..1514dadca8 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -128,6 +128,37 @@ 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()
+ ]])
+ eq(2, exec_lua [[
+ vim.api.nvim_set_current_buf(diagnostic_bufnr)
+ vim.opt_local.buflisted = false
+ return #vim.diagnostic.get()
+ ]])
+ eq(0, exec_lua [[
+ 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/ui_event_spec.lua b/test/functional/lua/ui_event_spec.lua
new file mode 100644
index 0000000000..294222ad13
--- /dev/null
+++ b/test/functional/lua/ui_event_spec.lua
@@ -0,0 +1,108 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local clear = helpers.clear
+local feed = helpers.feed
+local funcs = helpers.funcs
+local inspect = require'vim.inspect'
+
+describe('vim.ui_attach', function()
+ local screen
+ before_each(function()
+ clear()
+ exec_lua [[
+ ns = vim.api.nvim_create_namespace 'testspace'
+ events = {}
+ function on_event(event, ...)
+ events[#events+1] = {event, ...}
+ return true
+ end
+
+ function get_events()
+ local ret_events = events
+ events = {}
+ return ret_events
+ end
+ ]]
+
+ screen = Screen.new(40,5)
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1};
+ [2] = {bold = true};
+ [3] = {background = Screen.colors.Grey};
+ [4] = {background = Screen.colors.LightMagenta};
+ })
+ screen:attach()
+ end)
+
+ local function expect_events(expected)
+ local evs = exec_lua "return get_events(...)"
+ eq(expected, evs, inspect(evs))
+ end
+
+ it('can receive popupmenu events', function()
+ exec_lua [[ vim.ui_attach(ns, {ext_popupmenu=true}, on_event) ]]
+ feed('ifo')
+ screen:expect{grid=[[
+ fo^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]]}
+
+ funcs.complete(1, {'food', 'foobar', 'foo'})
+ screen:expect{grid=[[
+ food^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]]}
+ expect_events {
+ { "popupmenu_show", { { "food", "", "", "" }, { "foobar", "", "", "" }, { "foo", "", "", "" } }, 0, 0, 0, 1 };
+ }
+
+ feed '<c-n>'
+ screen:expect{grid=[[
+ foobar^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]]}
+ expect_events {
+ { "popupmenu_select", 1 };
+ }
+
+ feed '<c-y>'
+ screen:expect{grid=[[
+ foobar^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]], intermediate=true}
+ expect_events {
+ { "popupmenu_hide" };
+ }
+
+ -- vim.ui_detach() stops events, and reenables builtin pum immediately
+ exec_lua [[
+ vim.ui_detach(ns)
+ vim.fn.complete(1, {'food', 'foobar', 'foo'})
+ ]]
+
+ screen:expect{grid=[[
+ food^ |
+ {3:food }{1: }|
+ {4:foobar }{1: }|
+ {4:foo }{1: }|
+ {2:-- INSERT --} |
+ ]]}
+ expect_events {
+ }
+
+ end)
+end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 2b249b7a69..cd3240cd30 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -2721,6 +2721,57 @@ 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)
+
+ describe("vim.defaulttable", function()
+ it("creates nested table by default", function()
+ eq({ b = {c = 1 } }, exec_lua[[
+ local a = vim.defaulttable()
+ a.b.c = 1
+ return a
+ ]])
+ end)
+
+ it("allows to create default objects", function()
+ eq({ b = 1 }, exec_lua[[
+ local a = vim.defaulttable(function() return 0 end)
+ a.b = a.b + 1
+ return a
+ ]])
+ 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..e0035e2e8b 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -418,6 +418,42 @@ describe('LSP', function()
}
end)
+ it('should detach buffer on bufwipe', function()
+ local result = exec_lua([[
+ local server = function(dispatchers)
+ local closing = false
+ return {
+ request = function(method, params, callback)
+ if method == 'initialize' then
+ callback(nil, { capabilities = {} })
+ end
+ end,
+ notify = function(...)
+ end,
+ is_closing = function() return closing end,
+ terminate = function() closing = true end
+ }
+ end
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_set_current_buf(bufnr)
+ local client_id = vim.lsp.start({ name = 'detach-dummy', cmd = server })
+ assert(client_id, "lsp.start must return client_id")
+ local client = vim.lsp.get_client_by_id(client_id)
+ local num_attached_before = vim.tbl_count(client.attached_buffers)
+ vim.api.nvim_buf_delete(bufnr, { force = true })
+ local num_attached_after = vim.tbl_count(client.attached_buffers)
+ return {
+ bufnr = bufnr,
+ client_id = client_id,
+ num_attached_before = num_attached_before,
+ num_attached_after = num_attached_after,
+ }
+ ]])
+ eq(true, result ~= nil, "exec_lua must return result")
+ eq(1, result.num_attached_before)
+ eq(0, result.num_attached_after)
+ end)
+
it('client should return settings via workspace/configuration handler', function()
local expected_handlers = {
{NIL, {}, {method="shutdown", client_id=1}};
@@ -3180,5 +3216,79 @@ describe('LSP', function()
end,
}
end)
+ it('format formats range in visual mode', function()
+ local result = exec_lua([[
+ local messages = {}
+ local server = function(dispatchers)
+ local closing = false
+ return {
+ request = function(method, params, callback)
+ table.insert(messages, {
+ method = method,
+ params = params,
+ })
+ if method == 'initialize' then
+ callback(nil, {
+ capabilities = {
+ documentFormattingProvider = true,
+ documentRangeFormattingProvider = true,
+ }
+ })
+ end
+ end,
+ notify = function(...)
+ end,
+ is_closing = function()
+ return closing
+ end,
+ terminate = function()
+ closing = true
+ end
+ }
+ end
+ local bufnr = vim.api.nvim_get_current_buf()
+ local client_id = vim.lsp.start({ name = 'dummy', cmd = server })
+ vim.api.nvim_win_set_buf(0, bufnr)
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, {'foo', 'bar'})
+ vim.api.nvim_win_set_cursor(0, { 1, 0 })
+ vim.cmd.normal('v')
+ vim.api.nvim_win_set_cursor(0, { 2, 3 })
+ vim.lsp.buf.format({ bufnr = bufnr, false })
+ return messages
+ ]])
+ eq("textDocument/rangeFormatting", result[2].method)
+ local expected_range = {
+ start = { line = 0, character = 0 },
+ ['end'] = { line = 1, character = 4 },
+ }
+ eq(expected_range, result[2].params.range)
+ 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..3e63c5df9a 100644
--- a/test/functional/plugin/man_spec.lua
+++ b/test/functional/plugin/man_spec.lua
@@ -1,11 +1,18 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local command, eval, rawfeed = helpers.command, helpers.eval, helpers.rawfeed
+local command, rawfeed = helpers.command, helpers.rawfeed
local clear = helpers.clear
+local exec_lua = helpers.exec_lua
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()
@@ -44,7 +51,7 @@ describe(':Man', function()
|
]]}
- eval('man#init_pager()')
+ exec_lua[[require'man'.init_pager()]]
screen:expect([[
^this {b:is} {b:a} test |
@@ -68,7 +75,7 @@ describe(':Man', function()
|
]=]}
- eval('man#init_pager()')
+ exec_lua[[require'man'.init_pager()]]
screen:expect([[
^this {b:is }{bi:a }{biu:test} |
@@ -83,7 +90,7 @@ describe(':Man', function()
rawfeed([[
ithis i<C-v><C-h>is<C-v><C-h>s あ<C-v><C-h>あ test
with _<C-v><C-h>ö_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>̃_<C-v><C-h>c_<C-v><C-h>k te<C-v><ESC>[3mxt¶<C-v><ESC>[0m<ESC>]])
- eval('man#init_pager()')
+ exec_lua[[require'man'.init_pager()]]
screen:expect([[
^this {b:is} {b:あ} test |
@@ -99,7 +106,7 @@ describe(':Man', function()
i_<C-v><C-h>_b<C-v><C-h>be<C-v><C-h>eg<C-v><C-h>gi<C-v><C-h>in<C-v><C-h>ns<C-v><C-h>s
m<C-v><C-h>mi<C-v><C-h>id<C-v><C-h>d_<C-v><C-h>_d<C-v><C-h>dl<C-v><C-h>le<C-v><C-h>e
_<C-v><C-h>m_<C-v><C-h>i_<C-v><C-h>d_<C-v><C-h>__<C-v><C-h>d_<C-v><C-h>l_<C-v><C-h>e<ESC>]])
- eval('man#init_pager()')
+ exec_lua[[require'man'.init_pager()]]
screen:expect([[
{b:^_begins} |
@@ -115,7 +122,7 @@ describe(':Man', function()
i· ·<C-v><C-h>·
+<C-v><C-h>o
+<C-v><C-h>+<C-v><C-h>o<C-v><C-h>o double<ESC>]])
- eval('man#init_pager()')
+ exec_lua[[require'man'.init_pager()]]
screen:expect([[
^· {b:·} |
@@ -132,7 +139,7 @@ describe(':Man', function()
<C-v><C-[>[44m 4 <C-v><C-[>[45m 5 <C-v><C-[>[46m 6 <C-v><C-[>[47m 7 <C-v><C-[>[100m 8 <C-v><C-[>[101m 9
<C-v><C-[>[102m 10 <C-v><C-[>[103m 11 <C-v><C-[>[104m 12 <C-v><C-[>[105m 13 <C-v><C-[>[106m 14 <C-v><C-[>[107m 15
<C-v><C-[>[48:5:16m 16 <ESC>]])
- eval('man#init_pager()')
+ exec_lua[[require'man'.init_pager()]]
screen:expect([[
^ 0 1 2 3 |
diff --git a/test/functional/terminal/altscreen_spec.lua b/test/functional/terminal/altscreen_spec.lua
index 155a156d15..e4e1aa5fa2 100644
--- a/test/functional/terminal/altscreen_spec.lua
+++ b/test/functional/terminal/altscreen_spec.lua
@@ -126,13 +126,13 @@ describe(':terminal altscreen', function()
wait_removal()
feed('<c-\\><c-n>4k')
screen:expect([[
- ^line3 |
+ ^ |
|
|
rows: 4, cols: 50 |
|
]])
- eq(8, curbuf('line_count'))
+ eq(9, curbuf('line_count'))
end)
describe('and after exit', function()
@@ -142,15 +142,11 @@ describe(':terminal altscreen', function()
end)
it('restore buffer state', function()
- -- FIXME(tarruda): Note that the last line was lost after restoring the
- -- screen. This is a libvterm bug: When the main screen is restored it
- -- seems to "cut" lines that would have been left below the new visible
- -- screen.
screen:expect([[
- line4 |
line5 |
line6 |
line7 |
+ line8 |
{3:-- TERMINAL --} |
]])
end)
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 23b69319f0..36f9f90143 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -10,6 +10,7 @@ local retry = helpers.retry
local ok = helpers.ok
local iswin = helpers.iswin
local command = helpers.command
+local uname = helpers.uname
describe(':terminal', function()
local screen
@@ -45,6 +46,9 @@ describe(':terminal', function()
end)
it("reads output buffer on terminal reporting #4151", function()
+ if uname() == 'freebsd' then
+ pending('Failing FreeBSD test')
+ end
if helpers.pending_win32(pending) then return end
if iswin() then
feed_command([[terminal powershell -NoProfile -NoLogo -Command Write-Host -NoNewline "\"$([char]27)[6n\""; Start-Sleep -Milliseconds 500 ]])
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 99f69ef556..3c56ad5f79 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -21,6 +21,7 @@ local nvim_set = helpers.nvim_set
local ok = helpers.ok
local read_file = helpers.read_file
local funcs = helpers.funcs
+local meths = helpers.meths
if helpers.pending_win32(pending) then return end
@@ -297,6 +298,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
@@ -473,6 +667,57 @@ describe('TUI', function()
]], attrs)
end)
+ it('mouse events work with right-click menu', function()
+ child_session:request('nvim_command', [[
+ call setline(1, 'popup menu test')
+ set mouse=a mousemodel=popup
+
+ aunmenu PopUp
+ menu PopUp.foo :let g:menustr = 'foo'<CR>
+ menu PopUp.bar :let g:menustr = 'bar'<CR>
+ menu PopUp.baz :let g:menustr = 'baz'<CR>
+ highlight Pmenu ctermbg=NONE ctermfg=NONE cterm=underline,reverse
+ highlight PmenuSel ctermbg=NONE ctermfg=NONE cterm=underline,reverse,bold
+ ]])
+ local attrs = screen:get_default_attr_ids()
+ attrs[11] = {underline = true, reverse = true}
+ attrs[12] = {underline = true, reverse = true, bold = true}
+ meths.input_mouse('right', 'press', '', 0, 0, 4)
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }{11: foo }{4: }|
+ {4:~ }{11: bar }{4: }|
+ {4:~ }{11: baz }{4: }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]], attrs)
+ meths.input_mouse('right', 'release', '', 0, 0, 4)
+ screen:expect_unchanged()
+ meths.input_mouse('move', '', '', 0, 3, 6)
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }{11: foo }{4: }|
+ {4:~ }{11: bar }{4: }|
+ {4:~ }{12: baz }{4: }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]], attrs)
+ meths.input_mouse('left', 'press', '', 0, 2, 6)
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }|
+ {4:~ }|
+ {4:~ }|
+ {5:[No Name] [+] }|
+ :let g:menustr = 'bar' |
+ {3:-- TERMINAL --} |
+ ]], attrs)
+ meths.input_mouse('left', 'release', '', 0, 2, 6)
+ screen:expect_unchanged()
+ end)
+
it('paste: Insert mode', function()
-- "bracketed paste"
feed_data('i""\027i\027[200~')
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
index 5ec0a8a060..d557b2c012 100644
--- a/test/functional/treesitter/highlight_spec.lua
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -5,12 +5,14 @@ local clear = helpers.clear
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 +25,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,11 +106,11 @@ describe('treesitter highlighting', function()
}
exec_lua([[ hl_query = ... ]], hl_query)
+ command [[ hi link @error ErrorMsg ]]
+ command [[ hi link @warning WarningMsg ]]
end)
it('is updated with edits', function()
- if pending_c_parser(pending) then return end
-
insert(hl_text)
screen:expect{grid=[[
/// Schedule Lua callback on main loop's event queue |
@@ -271,8 +274,6 @@ describe('treesitter highlighting', function()
end)
it('is updated with :sort', function()
- if pending_c_parser(pending) then return end
-
insert(test_text)
exec_lua [[
local parser = vim.treesitter.get_parser(0, "c")
@@ -346,8 +347,6 @@ describe('treesitter highlighting', function()
end)
it("supports with custom parser", function()
- if pending_c_parser(pending) then return end
-
screen:set_default_attr_ids {
[1] = {bold = true, foreground = Screen.colors.SeaGreen4};
}
@@ -412,8 +411,6 @@ describe('treesitter highlighting', function()
end)
it("supports injected languages", function()
- if pending_c_parser(pending) then return end
-
insert([[
int x = INT_MAX;
#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
@@ -474,8 +471,6 @@ describe('treesitter highlighting', function()
end)
it("supports overriding queries, like ", function()
- if pending_c_parser(pending) then return end
-
insert([[
int x = INT_MAX;
#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
@@ -515,8 +510,6 @@ describe('treesitter highlighting', function()
end)
it("supports highlighting with custom highlight groups", function()
- if pending_c_parser(pending) then return end
-
insert(hl_text)
exec_lua [[
@@ -547,7 +540,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) |
@@ -572,8 +565,6 @@ describe('treesitter highlighting', function()
end)
it("supports highlighting with priority", function()
- if pending_c_parser(pending) then return end
-
insert([[
int x = INT_MAX;
#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
@@ -589,9 +580,9 @@ describe('treesitter highlighting', function()
-- expect everything to have Error highlight
screen:expect{grid=[[
{12:int}{8: x = INT_MAX;} |
- {8:#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))}|
- {8:#define foo void main() { \} |
- {8: return 42; \} |
+ {8:#define READ_STRING(x, y) (}{12:char_u}{8: *)read_string((x), (}{12:size_t}{8:)(y))}|
+ {8:#define foo }{12:void}{8: main() { \} |
+ {8: }{12:return}{8: 42; \} |
{8: }} |
^ |
{1:~ }|
@@ -612,11 +603,14 @@ 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()
- if pending_c_parser(pending) then return end
-
insert([[
char* x = "Will somebody ever read this?";
]])
@@ -642,11 +636,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,10 +666,32 @@ 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()
- if pending_c_parser(pending) then return end
insert(hl_text)
-- conceal can be empty or a single cchar.
@@ -712,32 +730,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..ed84dedb5a 100644
--- a/test/functional/treesitter/language_spec.lua
+++ b/test/functional/treesitter/language_spec.lua
@@ -6,11 +6,11 @@ local command = helpers.command
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,11 +26,12 @@ 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')"))
+
+ matches("Error executing lua: Failed to load parser: uv_dlsym: .+",
+ pcall_err(exec_lua, 'vim.treesitter.require_language("c", nil, false, "borklang")'))
end)
it('inspects language', function()
- if pending_c_parser(pending) then return end
-
local keys, fields, symbols = unpack(exec_lua([[
local lang = vim.treesitter.inspect_language('c')
local keys, symbols = {}, {}
@@ -70,7 +71,6 @@ describe('treesitter API', function()
end)
it('checks if vim.treesitter.get_parser tries to create a new parser on filetype change', function ()
- if pending_c_parser(pending) then return end
command("set filetype=c")
-- Should not throw an error when filetype is c
eq('c', exec_lua("return vim.treesitter.get_parser(0):lang()"))
@@ -79,5 +79,33 @@ 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 ()
+ 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 ()
+ 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..a82dce47b7 100644
--- a/test/functional/treesitter/node_spec.lua
+++ b/test/functional/treesitter/node_spec.lua
@@ -4,7 +4,6 @@ local clear = helpers.clear
local eq = helpers.eq
local exec_lua = helpers.exec_lua
local insert = helpers.insert
-local pending_c_parser = helpers.pending_c_parser
before_each(clear)
@@ -15,10 +14,6 @@ end
describe('treesitter node API', function()
clear()
- if pending_c_parser(pending) then
- return
- end
-
it('can move between siblings', function()
insert([[
int main(int x, int y, int z) {
@@ -59,4 +54,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/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index 7f3b0e770a..ccbd55df0e 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -5,13 +5,11 @@ local eq = helpers.eq
local insert = helpers.insert
local exec_lua = helpers.exec_lua
local feed = helpers.feed
-local pending_c_parser = helpers.pending_c_parser
before_each(clear)
describe('treesitter parser API', function()
clear()
- if pending_c_parser(pending) then return end
it('parses buffer', function()
if helpers.pending_win32(pending) then return end
@@ -249,7 +247,6 @@ void ui_refresh(void)
end)
it('supports getting text of multiline node', function()
- if pending_c_parser(pending) then return end
insert(test_text)
local res = exec_lua([[
local parser = vim.treesitter.get_parser(0, "c")
diff --git a/test/functional/treesitter/utils_spec.lua b/test/functional/treesitter/utils_spec.lua
new file mode 100644
index 0000000000..7f5a864c3d
--- /dev/null
+++ b/test/functional/treesitter/utils_spec.lua
@@ -0,0 +1,31 @@
+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
+
+before_each(clear)
+
+describe('treesitter utils', function()
+ before_each(clear)
+
+ it('can find an ancestor', function()
+
+ 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/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 789f1c6487..db5a775632 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -31,6 +31,8 @@ describe('decorations providers', function()
[12] = {foreground = tonumber('0x990000')};
[13] = {background = Screen.colors.LightBlue};
[14] = {background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue};
+ [15] = {special = Screen.colors.Blue1, undercurl = true},
+ [16] = {special = Screen.colors.Red, undercurl = true},
}
end)
@@ -56,7 +58,7 @@ describe('decorations providers', function()
a.nvim_set_decoration_provider(_G.ns1, {
on_start = on_do; on_buf = on_do;
on_win = on_do; on_line = on_do;
- on_end = on_do;
+ on_end = on_do; _on_spell_nav = on_do;
})
return _G.ns1
]])
@@ -95,7 +97,7 @@ describe('decorations providers', function()
|
]]}
check_trace {
- { "start", 4, 40 };
+ { "start", 4 };
{ "win", 1000, 1, 0, 8 };
{ "line", 1000, 1, 0 };
{ "line", 1000, 1, 1 };
@@ -119,7 +121,7 @@ describe('decorations providers', function()
|
]]}
check_trace {
- { "start", 5, 10 };
+ { "start", 5 };
{ "buf", 1 };
{ "win", 1000, 1, 0, 8 };
{ "line", 1000, 1, 6 };
@@ -156,6 +158,84 @@ describe('decorations providers', function()
]]}
end)
+ it('can indicate spellchecked points', function()
+ exec [[
+ set spell
+ set spelloptions=noplainbuffer
+ syntax off
+ ]]
+
+ insert [[
+ I am well written text.
+ i am not capitalized.
+ I am a speling mistakke.
+ ]]
+
+ setup_provider [[
+ local ns = a.nvim_create_namespace "spell"
+ beamtrace = {}
+ local function on_do(kind, ...)
+ if kind == 'win' or kind == 'spell' then
+ a.nvim_buf_set_extmark(0, ns, 0, 0, { end_row = 2, end_col = 23, spell = true, ephemeral = true })
+ end
+ table.insert(beamtrace, {kind, ...})
+ end
+ ]]
+
+ check_trace {
+ { "start", 5 };
+ { "win", 1000, 1, 0, 5 };
+ { "line", 1000, 1, 0 };
+ { "line", 1000, 1, 1 };
+ { "line", 1000, 1, 2 };
+ { "line", 1000, 1, 3 };
+ { "end", 5 };
+ }
+
+ feed "gg0"
+
+ screen:expect{grid=[[
+ ^I am well written text. |
+ {15:i} am not capitalized. |
+ I am a {16:speling} {16:mistakke}. |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed "]s"
+ check_trace {
+ { "spell", 1000, 1, 1, 0, 1, -1 };
+ }
+ screen:expect{grid=[[
+ I am well written text. |
+ {15:^i} am not capitalized. |
+ I am a {16:speling} {16:mistakke}. |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ feed "]s"
+ check_trace {
+ { "spell", 1000, 1, 2, 7, 2, -1 };
+ }
+ screen:expect{grid=[[
+ I am well written text. |
+ {15:i} am not capitalized. |
+ I am a {16:^speling} {16:mistakke}. |
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
it('can predefine highlights', function()
screen:try_resize(40, 16)
insert(mulholland)
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 4e3d62509c..dec8e0bc80 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -856,13 +856,14 @@ describe('CursorLine and CursorLineNr highlights', function()
|
]])
+ command('set fillchars=colorcol:.')
command('set colorcolumn=3')
feed('i <esc>')
screen:expect([[
- {1:{} {7: } |
+ {1:{} {7:.} |
"{2:a}{7:"} : {3:abc} {3:// 10;} |
- {1:}} {7: } |
- {5: ^ }{7: }{5: }|
+ {1:}} {7:.} |
+ {5: ^ }{7:.}{5: }|
|
]])
end)
@@ -2333,6 +2334,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/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index 9896b11218..8c5475ecce 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -1585,7 +1585,20 @@ describe('ui/mouse/input', function()
eq(0, meths.get_var('mouse_up2'))
end)
- it('feeding <MouseMove> does not use uninitialized memory #19480', function()
+ it('<MouseMove> is not translated into multiclicks and can be mapped', function()
+ meths.set_var('mouse_move', 0)
+ meths.set_var('mouse_move2', 0)
+ command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
+ command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
+ feed('<MouseMove><0,0>')
+ feed('<MouseMove><0,0>')
+ meths.input_mouse('move', '', '', 0, 0, 0)
+ meths.input_mouse('move', '', '', 0, 0, 0)
+ eq(4, meths.get_var('mouse_move'))
+ eq(0, meths.get_var('mouse_move2'))
+ end)
+
+ it('feeding <MouseMove> in Normal mode does not use uninitialized memory #19480', function()
feed('<MouseMove>')
helpers.poke_eventloop()
helpers.assert_alive()
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/options_spec.lua b/test/functional/ui/options_spec.lua
index 8d7c404637..bd0d2104db 100644
--- a/test/functional/ui/options_spec.lua
+++ b/test/functional/ui/options_spec.lua
@@ -19,6 +19,7 @@ describe('UI receives option updates', function()
linespace=0,
pumblend=0,
mousefocus=false,
+ mousemoveevent=false,
showtabline=1,
termguicolors=false,
ttimeout=true,
@@ -131,6 +132,12 @@ describe('UI receives option updates', function()
eq(expected, screen.options)
end)
+ command("set mousemoveevent")
+ expected.mousemoveevent = true
+ screen:expect(function()
+ eq(expected, screen.options)
+ end)
+
command("set nottimeout")
expected.ttimeout = false
screen:expect(function()
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index e11cd1e859..3c752875f0 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>')
@@ -2739,7 +2755,7 @@ describe('builtin popupmenu', function()
menu PopUp.bar :let g:menustr = 'bar'<CR>
menu PopUp.baz :let g:menustr = 'baz'<CR>
]])
- meths.input_mouse('right', 'press', '', 0, 0, 4)
+ feed('<RightMouse><4,0>')
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
@@ -2776,7 +2792,7 @@ describe('builtin popupmenu', function()
:let g:menustr = 'bar' |
]])
eq('bar', meths.get_var('menustr'))
- meths.input_mouse('right', 'press', '', 0, 1, 20)
+ feed('<RightMouse><20,1>')
screen:expect([[
^popup menu test |
{1:~ }|
@@ -2785,7 +2801,7 @@ describe('builtin popupmenu', function()
{1:~ }{n: baz }{1: }|
:let g:menustr = 'bar' |
]])
- meths.input_mouse('left', 'press', '', 0, 4, 22)
+ feed('<LeftMouse><22,4>')
screen:expect([[
^popup menu test |
{1:~ }|
@@ -2795,7 +2811,7 @@ describe('builtin popupmenu', function()
:let g:menustr = 'baz' |
]])
eq('baz', meths.get_var('menustr'))
- meths.input_mouse('right', 'press', '', 0, 0, 4)
+ feed('<RightMouse><4,0>')
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
@@ -2804,7 +2820,7 @@ describe('builtin popupmenu', function()
{1:~ }|
:let g:menustr = 'baz' |
]])
- meths.input_mouse('right', 'drag', '', 0, 3, 6)
+ feed('<RightDrag><6,3>')
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
@@ -2813,7 +2829,7 @@ describe('builtin popupmenu', function()
{1:~ }|
:let g:menustr = 'baz' |
]])
- meths.input_mouse('right', 'release', '', 0, 1, 6)
+ feed('<RightRelease><6,1>')
screen:expect([[
^popup menu test |
{1:~ }|
@@ -2823,6 +2839,38 @@ describe('builtin popupmenu', function()
:let g:menustr = 'foo' |
]])
eq('foo', meths.get_var('menustr'))
+ eq(false, screen.options.mousemoveevent)
+ feed('<RightMouse><4,0>')
+ screen:expect([[
+ ^popup menu test |
+ {1:~ }{n: foo }{1: }|
+ {1:~ }{n: bar }{1: }|
+ {1:~ }{n: baz }{1: }|
+ {1:~ }|
+ :let g:menustr = 'foo' |
+ ]])
+ eq(true, screen.options.mousemoveevent)
+ feed('<MouseMove><6,3>')
+ screen:expect([[
+ ^popup menu test |
+ {1:~ }{n: foo }{1: }|
+ {1:~ }{n: bar }{1: }|
+ {1:~ }{s: baz }{1: }|
+ {1:~ }|
+ :let g:menustr = 'foo' |
+ ]])
+ eq(true, screen.options.mousemoveevent)
+ feed('<LeftMouse><6,2>')
+ screen:expect([[
+ ^popup menu test |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ :let g:menustr = 'bar' |
+ ]])
+ eq(false, screen.options.mousemoveevent)
+ eq('bar', meths.get_var('menustr'))
end)
end)
@@ -3031,5 +3079,72 @@ describe('builtin popupmenu with ui/ext_multigrid', function()
:let g:menustr = 'foo' |
]]})
eq('foo', meths.get_var('menustr'))
+ eq(false, screen.options.mousemoveevent)
+ meths.input_mouse('right', 'press', '', 2, 0, 4)
+ screen:expect({grid=[[
+ ## grid 1
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [3:--------------------------------]|
+ ## grid 2
+ ^popup menu test |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ :let g:menustr = 'foo' |
+ ## grid 4
+ {n: foo }|
+ {n: bar }|
+ {n: baz }|
+ ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 100}}})
+ eq(true, screen.options.mousemoveevent)
+ meths.input_mouse('move', '', '', 2, 3, 6)
+ screen:expect({grid=[[
+ ## grid 1
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [3:--------------------------------]|
+ ## grid 2
+ ^popup menu test |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ :let g:menustr = 'foo' |
+ ## grid 4
+ {n: foo }|
+ {n: bar }|
+ {s: baz }|
+ ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 100}}})
+ eq(true, screen.options.mousemoveevent)
+ meths.input_mouse('left', 'press', '', 2, 2, 6)
+ screen:expect({grid=[[
+ ## grid 1
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [2:--------------------------------]|
+ [3:--------------------------------]|
+ ## grid 2
+ ^popup menu test |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ## grid 3
+ :let g:menustr = 'bar' |
+ ]]})
+ eq(false, screen.options.mousemoveevent)
+ eq('bar', meths.get_var('menustr'))
end)
end)
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/executable_spec.lua b/test/functional/vimscript/executable_spec.lua
index b4162b2336..b49eb09512 100644
--- a/test/functional/vimscript/executable_spec.lua
+++ b/test/functional/vimscript/executable_spec.lua
@@ -34,11 +34,13 @@ describe('executable()', function()
it('fails for invalid values', function()
for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do
- eq('Vim(call):E928: String required', exc_exec('call executable('..input..')'))
+ eq('Vim(call):E1174: String required for argument 1',
+ exc_exec('call executable('..input..')'))
end
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do
- eq('Vim(call):E928: String required', exc_exec('call executable('..input..')'))
+ eq('Vim(call):E1174: String required for argument 1',
+ exc_exec('call executable('..input..')'))
end
end)
diff --git a/test/functional/vimscript/exepath_spec.lua b/test/functional/vimscript/exepath_spec.lua
index bbca954511..439dd96fcd 100644
--- a/test/functional/vimscript/exepath_spec.lua
+++ b/test/functional/vimscript/exepath_spec.lua
@@ -21,12 +21,12 @@ describe('exepath()', function()
it('fails for invalid values', function()
for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do
- eq('Vim(call):E928: String required', exc_exec('call exepath('..input..')'))
+ eq('Vim(call):E1174: String required for argument 1', exc_exec('call exepath('..input..')'))
end
- eq('Vim(call):E1142: Non-empty string required', exc_exec('call exepath("")'))
+ eq('Vim(call):E1142: Non-empty string required for argument 1', exc_exec('call exepath("")'))
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do
- eq('Vim(call):E928: String required', exc_exec('call exepath('..input..')'))
+ eq('Vim(call):E1174: String required for argument 1', exc_exec('call exepath('..input..')'))
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/functional/vimscript/map_functions_spec.lua b/test/functional/vimscript/map_functions_spec.lua
index aa64006de0..96b86d053e 100644
--- a/test/functional/vimscript/map_functions_spec.lua
+++ b/test/functional/vimscript/map_functions_spec.lua
@@ -3,6 +3,8 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
local eval = helpers.eval
+local exec = helpers.exec
+local exec_lua = helpers.exec_lua
local expect = helpers.expect
local feed = helpers.feed
local funcs = helpers.funcs
@@ -10,6 +12,7 @@ local meths = helpers.meths
local nvim = helpers.nvim
local source = helpers.source
local command = helpers.command
+local pcall_err = helpers.pcall_err
describe('maparg()', function()
before_each(clear)
@@ -194,4 +197,43 @@ describe('mapset()', function()
feed('foo')
expect('<<lt><')
end)
+
+ it('can restore Lua callback from the dict returned by maparg()', function()
+ eq(0, exec_lua([[
+ GlobalCount = 0
+ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
+ return GlobalCount
+ ]]))
+ feed('asdf')
+ eq(1, exec_lua([[return GlobalCount]]))
+
+ exec_lua([[
+ _G.saved_asdf_map = vim.fn.maparg('asdf', 'n', false, true)
+ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 10 end })
+ ]])
+ feed('asdf')
+ eq(11, exec_lua([[return GlobalCount]]))
+
+ exec_lua([[vim.fn.mapset('n', false, _G.saved_asdf_map)]])
+ feed('asdf')
+ eq(12, exec_lua([[return GlobalCount]]))
+
+ exec([[
+ let g:saved_asdf_map = maparg('asdf', 'n', v:false, v:true)
+ lua vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 10 end })
+ ]])
+ feed('asdf')
+ eq(22, exec_lua([[return GlobalCount]]))
+
+ command([[call mapset('n', v:false, g:saved_asdf_map)]])
+ feed('asdf')
+ eq(23, exec_lua([[return GlobalCount]]))
+ end)
+
+ it('does not leak memory if lhs is missing', function()
+ eq('Error executing lua: Vim:E460: entries missing in mapset() dict argument',
+ pcall_err(exec_lua, [[vim.fn.mapset('n', false, {rhs = 'foo'})]]))
+ eq('Error executing lua: Vim:E460: entries missing in mapset() dict argument',
+ pcall_err(exec_lua, [[vim.fn.mapset('n', false, {callback = function() end})]]))
+ end)
end)
diff --git a/test/helpers.lua b/test/helpers.lua
index 7ec9beea92..499b91488b 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -790,10 +790,9 @@ end
function module.isCI(name)
local any = (name == nil)
- assert(any or name == 'sourcehut' or name == 'github')
- local sh = ((any or name == 'sourcehut') and nil ~= os.getenv('SOURCEHUT'))
+ assert(any or name == 'github')
local gh = ((any or name == 'github') and nil ~= os.getenv('GITHUB_ACTIONS'))
- return sh or gh
+ return gh
end
diff --git a/test/unit/message_spec.lua b/test/unit/message_spec.lua
index 7e92b5c857..549eff6e03 100644
--- a/test/unit/message_spec.lua
+++ b/test/unit/message_spec.lua
@@ -22,7 +22,7 @@ describe('trunc_string', function()
local function test_copy(s, expected, room)
room = room and room or 20
local buf = cimp.xmalloc(ffi.sizeof('char_u') * buflen)
- local str = cimp.vim_strsave(to_cstr(s))
+ local str = cimp.xstrdup(to_cstr(s))
cimp.trunc_string(str, buf, room, buflen)
eq(expected, ffi.string(buf))
cimp.xfree(buf)
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)