diff options
76 files changed, 6359 insertions, 4045 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f75320048b..0dbe484108 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: jobs: unixish: - name: ${{ matrix.os }} ${{ matrix.flavor }} (cc=${{ matrix.cc }}) + name: ${{ matrix.runner }} ${{ matrix.flavor }} (cc=${{ matrix.cc }}) strategy: fail-fast: false matrix: @@ -30,6 +30,9 @@ jobs: - cc: clang runner: macos-10.15 os: osx + - cc: clang + runner: macos-11.0 + os: osx - flavor: functionaltest-lua cc: gcc runner: ubuntu-20.04 @@ -80,7 +83,7 @@ jobs: path: | ${{ env.CACHE_NVIM_DEPS_DIR }} ~/.ccache - key: ${{ runner.os }}-${{ matrix.flavor }}-${{ matrix.cc }}-${{ hashFiles('cmake/*', 'third-party/**', '**/CMakeLists.txt') }}-${{ github.base_ref }} + key: ${{ matrix.runner }}-${{ matrix.flavor }}-${{ matrix.cc }}-${{ hashFiles('cmake/*', 'third-party/**', '**/CMakeLists.txt') }}-${{ github.base_ref }} - name: Build third-party run: ./ci/before_script.sh diff --git a/.github/workflows/commitlint.config.js b/.github/workflows/commitlint.config.js deleted file mode 100644 index 5f10ffc6f4..0000000000 --- a/.github/workflows/commitlint.config.js +++ /dev/null @@ -1,35 +0,0 @@ -module.exports = { - rules: { - 'body-leading-blank': [1, 'always'], - 'body-max-line-length': [2, 'always', 100], - 'footer-leading-blank': [1, 'always'], - 'footer-max-line-length': [2, 'always', 100], - 'header-max-length': [2, 'always', 100], - 'scope-case': [2, 'always', 'lower-case'], - 'subject-case': [ - 2, - 'never', - ['sentence-case', 'start-case', 'pascal-case', 'upper-case'], - ], - 'subject-empty': [2, 'never'], - 'subject-full-stop': [2, 'never', '.'], - 'type-case': [2, 'always', 'lower-case'], - 'type-empty': [2, 'never'], - 'type-enum': [ - 2, - 'always', - [ - 'build', - 'chore', - 'ci', - 'docs', - 'feat', - 'fix', - 'perf', - 'refactor', - 'revert', - 'test', - ], - ], - }, -}; diff --git a/.github/workflows/commitlint.config_patch.js b/.github/workflows/commitlint.config_patch.js deleted file mode 100644 index ca398c45dc..0000000000 --- a/.github/workflows/commitlint.config_patch.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = { - parserPreset: { - parserOpts: { headerPattern: /^([^\(\):]*)(?:\((.*)\))?!?:(.*)$/ } - }, - rules: { - 'body-leading-blank': [1, 'always'], - 'body-max-line-length': [2, 'always', 100], - 'footer-max-line-length': [2, 'always', 100], - 'scope-case': [2, 'always', 'lower-case'], - 'subject-case': [ - 2, - 'never', - ['sentence-case', 'start-case', 'pascal-case', 'upper-case'], - ], - 'subject-empty': [2, 'never'], - 'subject-full-stop': [2, 'never', '.'], - 'type-case': [2, 'always', 'lower-case'], - 'type-empty': [2, 'never'], - 'type-enum': [ - 2, - 'always', - [ - 'vim-patch', - ], - ], - }, -}; diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 9ae138fbd7..4c9c526946 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -9,10 +9,8 @@ jobs: - uses: actions/checkout@v2.3.1 with: fetch-depth: 0 - - run: npm install --save-dev @commitlint/cli - - run: | - if [[ "$(gh pr view ${{ github.event.pull_request.number }} --json commits --jq '.[][0].messageHeadline')" == vim-patch* ]];then - npx commitlint --from HEAD~1 --to HEAD --verbose --help-url https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#commit-messages --config .github/workflows/commitlint.config_patch.js - else - npx commitlint --from HEAD~1 --to HEAD --verbose --help-url https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#commit-messages --config .github/workflows/commitlint.config.js - fi + - uses: rhysd/action-setup-vim@v1 + with: + neovim: true + - run: gh pr checkout ${{ github.event.pull_request.number }} + - run: nvim --clean -es +"lua require('scripts.lintcommit').main({trace=true})" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2a565574fa..88d2989f13 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -217,13 +217,20 @@ You can lint a single file (but this will _not_ exclude legacy errors): ### Style -The repo includes a `.clang-format` config file which (mostly) matches the -[style-guide]. You can use `clang-format` to format code with the `gq` -operator in Nvim: - - if !empty(findfile('.clang-format', ';')) - setlocal formatprg=clang-format\ -style=file - endif +- Style rules are (mostly) defined by `src/uncrustify.cfg` which tries to match + the [style-guide]. To use the Nvim `gq` command with `uncrustify`: + ``` + if !empty(findfile('src/.uncrustify', ';')) + setlocal formatprg=uncrustify\ -q\ -c\ src/uncrustify.cfg\ --replace\ --no-backup + endif + ``` +- There is also `.clang-format` which has drifted from the [style-guide], but + is available for reference. To use the Nvim `gq` command with `clang-format`: + ``` + if !empty(findfile('.clang-format', ';')) + setlocal formatprg=clang-format\ -style=file + endif + ``` ### Navigate @@ -263,7 +270,7 @@ as context, use the `-W` argument as well. [1820]: https://github.com/neovim/neovim/pull/1820 [hub]: https://hub.github.com/ [conventional_commits]: https://www.conventionalcommits.org -[style-guide]: http://neovim.io/develop/style-guide.xml +[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 @@ -278,3 +285,4 @@ as context, use the `-W` argument as well. [wiki-contribute-help]: https://github.com/neovim/neovim/wiki/contribute-%3Ahelp [pr-draft]: https://docs.github.com/en/github/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 +[uncrustify]: https://formulae.brew.sh/formula/uncrustify diff --git a/runtime/doc/dev_style.txt b/runtime/doc/dev_style.txt new file mode 100644 index 0000000000..82f279e781 --- /dev/null +++ b/runtime/doc/dev_style.txt @@ -0,0 +1,1159 @@ +*dev_style.txt* Nvim + + + NVIM REFERENCE MANUAL + + +Nvim style guide *dev-style* + +This is style guide for developers working on Nvim's source code. + +License: CC-By 3.0 http://creativecommons.org/licenses/by/3.0/ + + Type |gO| to see the table of contents. + +============================================================================== +Background + +One way in which we keep the code base manageable is by enforcing consistency. +It is very important that any programmer be able to look at another's code and +quickly understand it. + +Maintaining a uniform style and following conventions means that we can more +easily use "pattern-matching" to infer what various symbols are and what +invariants are true about them. Creating common, required idioms and patterns +makes code much easier to understand. + +In some cases there might be good arguments for changing certain style rules, +but we nonetheless keep things as they are in order to preserve consistency. + + +============================================================================== +Header Files *dev-style-header* + + +The #define Guard ~ + +All header files should have `#define` guards to prevent multiple inclusion. +The format of the symbol name should be `NVIM_<DIRECTORY>_<FILE>_H`. + + In foo/bar.h: +> + #ifndef NVIM_FOO_BAR_H + #define NVIM_FOO_BAR_H + + ... + + #endif // NVIM_FOO_BAR_H +< + + +Names and Order of Includes ~ + +Use standard order for readability and to avoid hidden dependencies: C +library, other libraries' `.h`, your project's `.h`. + + In foo.c order your includes as follows: + + 1. C system files. + 2. Other libraries' `.h` files. + 3. Your project's `.h` files. + + Exception: sometimes, system-specific code needs conditional includes. + Such code can put conditional includes after other includes. Of course, + keep your system-specific code small and localized. + + +Constants ~ + +Do not use macros to define constants in headers. + +Macro constants in header files cannot be used by unit tests. + +However, you are allowed to define a macro that holds the same value as a +non-enum constant (defined in the same header) if the value of the constant +represents the size of an array. + + +============================================================================== +Scoping *dev-style-scope* + +Local Variables ~ + +Place a function's variables in the narrowest scope possible, and initialize +variables in the declaration. + +C99 allows you to declare variables anywhere in a function. Declare them in as +local a scope as possible, and as close to the first use as possible. This +makes it easier for the reader to find the declaration and see what type the +variable is and what it was initialized to. In particular, initialization +should be used instead of declaration and assignment, e.g. > + + int i; + i = f(); // BAD: initialization separate from declaration. + + int j = g(); // GOOD: declaration has initialization. + + +============================================================================== +Nvim-Specific Magic + +clint ~ + +Use `clint.py` to detect style errors. + +`src/clint.py` is a Python script that reads a source file and identifies +style errors. It is not perfect, and has both false positives and false +negatives, but it is still a valuable tool. False positives can be ignored by +putting `// NOLINT` at the end of the line. + +uncrustify ~ + +src/uncrustify.cfg is the authority for expected code formatting, for cases +not covered by clint.py. We remove checks in clint.py if they are covered by +uncrustify rules. + +============================================================================== +Other C Features *dev-style-features* + + +Variable-Length Arrays and alloca() ~ + +We do not allow variable-length arrays or `alloca()`. + +Variable-length arrays can cause hard to detect stack overflows. + + +Postincrement and Postdecrement ~ + +Use postfix form (`i++`) in statements. > + + for (int i = 0; i < 3; i++) { } + int j = ++i; // OK: ++i is used as an expression. + + for (int i = 0; i < 3; ++i) { } + ++i; // BAD: ++i is used as a statement. + + +Use of const ~ + +Use `const` pointers whenever possible. Avoid `const` on non-pointer parameter definitions. + + Where to put the const ~ + + Some people favor the form `int const *foo` to `const int *foo` . They + argue that this is more readable because it's more consistent: it keeps + the rule that `const` always follows the object it's describing. However, + this consistency argument doesn't apply in codebases with few + deeply-nested pointer expressions since most `const` expressions have only + one `const`, and it applies to the underlying value. In such cases, there's + no consistency to maintain. Putting the `const` first is arguably more + readable, since it follows English in putting the "adjective" (`const`) + before the "noun" (`int`). + + That said, while we encourage putting `const` first, we do not require it. + But be consistent with the code around you! > + + void foo(const char *p, int i); + } + + int foo(const int a, const bool b) { + } + + int foo(int *const p) { + } + + +Integer Types ~ + +Of the built-in integer types only use `char`, `int`, `uint8_t`, `int8_t`, +`uint16_t`, `int16_t`, `uint32_t`, `int32_t`, `uint64_t`, `int64_t`, +`uintmax_t`, `intmax_t`, `size_t`, `ssize_t`, `uintptr_t`, `intptr_t`, and +`ptrdiff_t`. + +Use `int` for error codes and local, trivial variables only. + +Use care when converting integer types. Integer conversions and promotions can +cause non-intuitive behavior. Note that the signedness of `char` is +implementation defined. + +Public facing types must have fixed width (`uint8_t`, etc.) + +There are no convenient `printf` format placeholders for fixed width types. +Cast to `uintmax_t` or `intmax_t` if you have to format fixed width integers. + +Type unsigned signed +`char` `%hhu` `%hhd` +`int` n/a `%d` +`(u)intmax_t` `%ju` `%jd` +`(s)size_t` `%zu` `%zd` +`ptrdiff_t` `%tu` `%td` + + +Booleans ~ + +Use `bool` to represent boolean values. > + + int loaded = 1; // BAD: loaded should have type bool. + + +Variable declarations ~ + +Declare only one variable per line. > + + int i, j = 1 + + +Conditions ~ + +Don't use "yoda-conditions". Use at most one assignment per condition. > + + if (1 == x) { + + if (x == 1) { //use this order + + if ((x = f()) && (y = g())) { + + +Function declarations ~ + +Every function must not have a separate declaration. + +Function declarations are created by the gendeclarations.lua script. > + + static void f(void); + + static void f(void) + { + ... + } + + +General translation unit layout ~ + +The definitions of public functions precede the definitions of static +functions. > + + <HEADER> + + <PUBLIC FUNCTION DEFINITIONS> + + <STATIC FUNCTION DEFINITIONS> + + +Integration with declarations generator ~ + +Every C file must contain #include of the generated header file, guarded by +#ifdef INCLUDE_GENERATED_DECLARATIONS. + +Include must go after other #includes and typedefs in .c files and after +everything else in header files. It is allowed to omit #include in a .c file +if .c file does not contain any static functions. + +Included file name consists of the .c file name without extension, preceded by +the directory name relative to src/nvim. Name of the file containing static +functions declarations ends with `.c.generated.h`, `*.h.generated.h` files +contain only non-static function declarations. > + + // src/nvim/foo.c file + #include <stddef.h> + + typedef int FooType; + + #ifdef INCLUDE_GENERATED_DECLARATIONS + # include "foo.c.generated.h" + #endif + + … + + + // src/nvim/foo.h file + #ifndef NVIM_FOO_H + #define NVIM_FOO_H + + … + + #ifdef INCLUDE_GENERATED_DECLARATIONS + # include "foo.h.generated.h" + #endif + #endif // NVIM_FOO_H + + +64-bit Portability ~ + +Code should be 64-bit and 32-bit friendly. Bear in mind problems of printing, +comparisons, and structure alignment. + +- Remember that `sizeof(void *)` != `sizeof(int)`. Use `intptr_t` if you want + a pointer-sized integer. + +- You may need to be careful with structure alignments, particularly for + structures being stored on disk. Any class/structure with a + `int64_t`/`uint64_t` member will by default end up being 8-byte aligned on a + 64-bit system. If you have such structures being shared on disk between + 32-bit and 64-bit code, you will need to ensure that they are packed the + same on both architectures. Most compilers offer a way to alter structure + alignment. For gcc, you can use `__attribute__((packed))`. MSVC offers + `#pragma pack()` and `__declspec(align())`. + +- Use the `LL` or `ULL` suffixes as needed to create 64-bit constants. For + example: > + + int64_t my_value = 0x123456789LL; + uint64_t my_mask = 3ULL << 48; + + +sizeof ~ + +Prefer `sizeof(varname)` to `sizeof(type)`. + +Use `sizeof(varname)` when you take the size of a particular variable. +`sizeof(varname)` will update appropriately if someone changes the variable +type either now or later. You may use `sizeof(type)` for code unrelated to any +particular variable, such as code that manages an external or internal data +format where a variable of an appropriate C type is not convenient. > + + Struct data; + memset(&data, 0, sizeof(data)); + + memset(&data, 0, sizeof(Struct)); + + if (raw_size < sizeof(int)) { + fprintf(stderr, "compressed record not big enough for count: %ju", raw_size); + return false; + } + + +============================================================================== +Naming *dev-style-naming* + +The most important consistency rules are those that govern naming. The style +of a name immediately informs us what sort of thing the named entity is: a +type, a variable, a function, a constant, a macro, etc., without requiring us +to search for the declaration of that entity. The pattern-matching engine in +our brains relies a great deal on these naming rules. + +Naming rules are pretty arbitrary, but we feel that consistency is more +important than individual preferences in this area, so regardless of whether +you find them sensible or not, the rules are the rules. + + +General Naming Rules ~ + +Function names, variable names, and filenames should be descriptive; eschew +abbreviation. + +Give as descriptive a name as possible, within reason. Do not worry about +saving horizontal space as it is far more important to make your code +immediately understandable by a new reader. Do not use abbreviations that are +ambiguous or unfamiliar to readers outside your project, and do not abbreviate +by deleting letters within a word. > + + int price_count_reader; // No abbreviation. + int num_errors; // "num" is a widespread convention. + int num_dns_connections; // Most people know what "DNS" stands for. + + int n; // Meaningless. + int nerr; // Ambiguous abbreviation. + int n_comp_conns; // Ambiguous abbreviation. + int wgc_connections; // Only your group knows what this stands for. + int pc_reader; // Lots of things can be abbreviated "pc". + int cstmr_id; // Deletes internal letters. + + +File Names ~ + +Filenames should be all lowercase and can include underscores (`_`). + +Use underscores to separate words. Examples of acceptable file names: > + + my_useful_file.c + getline_fix.c // OK: getline refers to the glibc function. + +C files should end in `.c` and header files should end in `.h`. + +Do not use filenames that already exist in `/usr/include`, such as `db.h`. + +In general, make your filenames very specific. For example, use +`http_server_logs.h` rather than `logs.h`. + + +Type Names ~ + +Typedef-ed structs and enums start with a capital letter and have a capital +letter for each new word, with no underscores: `MyExcitingStruct`. + +Non-Typedef-ed structs and enums are all lowercase with underscores between +words: `struct my_exciting_struct` . > + + struct my_struct { + ... + }; + typedef struct my_struct MyAwesomeStruct; + + +Variable Names ~ + +Variable names are all lowercase, with underscores between words. For +instance: `my_exciting_local_variable`. + + Common Variable names ~ + + For example: > + + string table_name; // OK: uses underscore. + string tablename; // OK: all lowercase. + + string tableName; // BAD: mixed case. +< + + Struct Variables ~ + + Data members in structs should be named like regular variables. > + + struct url_table_properties { + string name; + int num_entries; + } +< + + Global Variables ~ + + Don't use global variables unless absolutely necessary. Prefix global + variables with `g_`. + + +Constant Names ~ + +Use a `k` followed by mixed case: `kDaysInAWeek`. + +All compile-time constants, whether they are declared locally or globally, +follow a slightly different naming convention from other variables. Use a `k` +followed by words with uppercase first letters: > + + const int kDaysInAWeek = 7; + +Function Names ~ + +Function names are all lowercase, with underscores between words. For +instance: `my_exceptional_function()`. All functions in the same header file +should have a common prefix. + +In `os_unix.h`: > + + void unix_open(const char *path); + void unix_user_id(void); + +If your function crashes upon an error, you should append `or_die` to the +function name. This only applies to functions which could be used by +production code and to errors that are reasonably likely to occur during +normal operation. + + +Enumerator Names ~ + +Enumerators should be named like constants: `kEnumName`. > + + enum url_table_errors { + kOK = 0, + kErrorOutOfMemory, + kErrorMalformedInput, + }; + + +Macro Names ~ + +They're like this: `MY_MACRO_THAT_SCARES_CPP_DEVELOPERS`. > + + #define ROUND(x) ... + #define PI_ROUNDED 5.0 + + +============================================================================== +Comments *dev-style-comments* + +Comments are vital to keeping our code readable. The following rules describe +what you should comment and where. But remember: while comments are very +important, the best code is self-documenting. + +When writing your comments, write for your audience: the next contributor who +will need to understand your code. Be generous — the next one may be you! + +Nvim uses Doxygen comments. + + +Comment Style ~ + +Use the `//`-style syntax only. > + + // This is a comment spanning + // multiple lines + f(); + + +File Comments ~ + +Start each file with a description of its contents. + + Legal Notice ~ + + We have no such thing. These things are in LICENSE and only there. + + File Contents ~ + + Every file should have a comment at the top describing its contents. + + Generally a `.h` file will describe the variables and functions that are + declared in the file with an overview of what they are for and how they + are used. A `.c` file should contain more information about implementation + details or discussions of tricky algorithms. If you feel the + implementation details or a discussion of the algorithms would be useful + for someone reading the `.h`, feel free to put it there instead, but + mention in the `.c` that the documentation is in the `.h` file. + + Do not duplicate comments in both the `.h` and the `.c`. Duplicated + comments diverge. > + + /// A brief description of this file. + /// + /// A longer description of this file. + /// Be very generous here. + + +Struct Comments ~ + +Every struct definition should have accompanying comments that describes what +it is for and how it should be used. > + + /// 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 g_wininfo. It is kept in + /// most-recently-used order. + struct win_info { + /// Next entry or NULL for last entry. + WinInfo *wi_next; + /// Previous entry or NULL for first entry. + WinInfo *wi_prev; + /// Pointer to window that did the wi_fpos. + Win *wi_win; + ... + }; + +If the field comments are short, you can also put them next to the field. But +be consistent within one struct. > + + struct wininfo_S { + WinInfo *wi_next; /// Next entry or NULL for last entry. + WinInfo *wi_prev; /// Previous entry or NULL for first entry. + Win *wi_win; /// Pointer to window that did the wi_fpos. + ... + }; + +If you have already described a struct in detail in the comments at the top of +your file feel free to simply state "See comment at top of file for a complete +description", but be sure to have some sort of comment. + +Document the synchronization assumptions the struct makes, if any. If an +instance of the struct can be accessed by multiple threads, take extra care to +document the rules and invariants surrounding multithreaded use. + + +Function Comments ~ + +Declaration comments describe use of the function; comments at the definition +of a function describe operation. + + Function Declarations ~ + + Every function declaration should have comments immediately preceding it + that describe what the function does and how to use it. These comments + should be descriptive ("Opens the file") rather than imperative ("Open the + file"); the comment describes the function, it does not tell the function + what to do. In general, these comments do not describe how the function + performs its task. Instead, that should be left to comments in the + function definition. + + Types of things to mention in comments at the function declaration: + + - If the function allocates memory that the caller must free. + - Whether any of the arguments can be a null pointer. + - If there are any performance implications of how a function is used. + - If the function is re-entrant. What are its synchronization assumptions? + > + /// Brief description of the function. + /// + /// Detailed description. + /// May span multiple paragraphs. + /// + /// @param arg1 Description of arg1 + /// @param arg2 Description of arg2. May span + /// multiple lines. + /// + /// @return Description of the return value. + Iterator *get_iterator(void *arg1, void *arg2); +< + + Function Definitions ~ + + If there is anything tricky about how a function does its job, the + function definition should have an explanatory comment. For example, in + the definition comment you might describe any coding tricks you use, give + an overview of the steps you go through, or explain why you chose to + implement the function in the way you did rather than using a viable + alternative. For instance, you might mention why it must acquire a lock + for the first half of the function but why it is not needed for the second + half. + + Note you should not just repeat the comments given with the function + declaration, in the `.h` file or wherever. It's okay to recapitulate + briefly what the function does, but the focus of the comments should be on + how it does it. > + + // Note that we don't use Doxygen comments here. + Iterator *get_iterator(void *arg1, void *arg2) + { + ... + } + + +Variable Comments ~ + +In general the actual name of the variable should be descriptive enough to +give a good idea of what the variable is used for. In certain cases, more +comments are required. + + Global Variables ~ + + All global variables should have a comment describing what they are and + what they are used for. For example: > + + /// The total number of tests cases that we run + /// through in this regression test. + const int kNumTestCases = 6; + + +Implementation Comments ~ + +In your implementation you should have comments in tricky, non-obvious, +interesting, or important parts of your code. + + Line Comments ~ + + Also, lines that are non-obvious should get a comment at the end of the + line. These end-of-line comments should be separated from the code by 2 + spaces. Example: > + + // If we have enough memory, mmap the data portion too. + mmap_budget = max<int64>(0, mmap_budget - index_->length()); + if (mmap_budget >= data_size_ && !MmapData(mmap_chunk_bytes, mlock)) { + return; // Error already logged. + } +< + Note that there are both comments that describe what the code is doing, + and comments that mention that an error has already been logged when the + function returns. + + If you have several comments on subsequent lines, it can often be more + readable to line them up: > + + do_something(); // Comment here so the comments line up. + do_something_else_that_is_longer(); // Comment here so there are two spaces between + // the code and the comment. + { // One space before comment when opening a new scope is allowed, + // thus the comment lines up with the following comments and code. + do_something_else(); // Two spaces before line comments normally. + } +< + + NULL, true/false, 1, 2, 3... ~ + + When you pass in a null pointer, boolean, or literal integer values to + functions, you should consider adding a comment about what they are, or + make your code self-documenting by using constants. For example, compare: + > + + bool success = calculate_something(interesting_value, + 10, + false, + NULL); // What are these arguments?? +< + + versus: > + + bool success = calculate_something(interesting_value, + 10, // Default base value. + false, // Not the first time we're calling this. + NULL); // No callback. +< + + Or alternatively, constants or self-describing variables: > + + const int kDefaultBaseValue = 10; + const bool kFirstTimeCalling = false; + Callback *null_callback = NULL; + bool success = calculate_something(interesting_value, + kDefaultBaseValue, + kFirstTimeCalling, + null_callback); +< + + Don'ts ~ + + Note that you should never describe the code itself. Assume that the + person reading the code knows C better than you do, even though he or she + does not know what you are trying to do: > + + // Now go through the b array and make sure that if i occurs, + // the next element is i+1. + ... // Geez. What a useless comment. + + +Punctuation, Spelling and Grammar ~ + +Pay attention to punctuation, spelling, and grammar; it is easier to read +well-written comments than badly written ones. + +Comments should be as readable as narrative text, with proper capitalization +and punctuation. In many cases, complete sentences are more readable than +sentence fragments. Shorter comments, such as comments at the end of a line of +code, can sometimes be less formal, but you should be consistent with your +style. + +Although it can be frustrating to have a code reviewer point out that you are +using a comma when you should be using a semicolon, it is very important that +source code maintain a high level of clarity and readability. Proper +punctuation, spelling, and grammar help with that goal. + + +TODO Comments ~ + +Use `TODO` comments for code that is temporary, a short-term solution, or +good-enough but not perfect. + +`TODO`s should include the string `TODO` in all caps, followed by the name, +email address, or other identifier of the person who can best provide context +about the problem referenced by the `TODO`. The main purpose is to have a +consistent `TODO` format that can be searched to find the person who can +provide more details upon request. A `TODO` is not a commitment that the +person referenced will fix the problem. Thus when you create a `TODO`, it is +almost always your name that is given. > + + // TODO(kl@gmail.com): Use a "*" here for concatenation operator. + // TODO(Zeke): change this to use relations. + +If your `TODO` is of the form "At a future date do something" make sure that +you either include a very specific date ("Fix by November 2005") or a very +specific event ("Remove this code when all clients can handle XML +responses."). + + +Deprecation Comments ~ + +Mark deprecated interface points with `@deprecated` docstring token. + +You can mark an interface as deprecated by writing a comment containing the +word `@deprecated` in all caps. The comment goes either before the declaration +of the interface or on the same line as the declaration. + +After `@deprecated`, write your name, email, or other identifier in +parentheses. + +A deprecation comment must include simple, clear directions for people to fix +their callsites. In C, you can implement a deprecated function as an inline +function that calls the new interface point. + +Marking an interface point `DEPRECATED` will not magically cause any callsites +to change. If you want people to actually stop using the deprecated facility, +you will have to fix the callsites yourself or recruit a crew to help you. + +New code should not contain calls to deprecated interface points. Use the new +interface point instead. If you cannot understand the directions, find the +person who created the deprecation and ask them for help using the new +interface point. + + +============================================================================== +Formatting *dev-style-format* + +Coding style and formatting are pretty arbitrary, but a project is much easier +to follow if everyone uses the same style. Individuals may not agree with +every aspect of the formatting rules, and some of the rules may take some +getting used to, but it is important that all project contributors follow the +style rules so that they can all read and understand everyone's code easily. + + +Line Length ~ + +Each line of text in your code should be at most 100 characters long. + +Exception: if a comment line contains an example command or a literal URL +longer than 100 characters, that line may be longer than 100 characters for ease +of cut and paste. + + +Non-ASCII Characters ~ + +Non-ASCII characters should be rare, and must use UTF-8 formatting. + +You shouldn't hard-code user-facing text in source (OR SHOULD YOU?), even +English, so use of non-ASCII characters should be rare. However, in certain +cases it is appropriate to include such words in your code. For example, if +your code parses data files from foreign sources, it may be appropriate to +hard-code the non-ASCII string(s) used in those data files as delimiters. More +commonly, unittest code (which does not need to be localized) might contain +non-ASCII strings. In such cases, you should use UTF-8, since that is an +encoding understood by most tools able to handle more than just ASCII. + +Hex encoding is also OK, and encouraged where it enhances readability — for +example, `"\uFEFF"`, is the Unicode zero-width no-break space character, which +would be invisible if included in the source as straight UTF-8. + + +Spaces vs. Tabs ~ + +Use only spaces, and indent 2 spaces at a time. Do not use tabs in your code. + + +Function Declarations and Definitions ~ + +Return type on the same line as function name, parameters on the same line if +they fit. + +Functions look like this: > + + ReturnType function_name(Type par_name1, Type par_name2) + { + do_something(); + ... + } + +If you have too much text to fit on one line: > + + ReturnType really_long_function_name(Type par_name1, Type par_name2, + Type par_name3) + { + do_something(); + ... + } + +or if you cannot fit even the first parameter (but only then): > + + ReturnType really_really_really_long_function_name( + Type par_name1, // 4 space indent + Type par_name2, + Type par_name3) + { + do_something(); // 2 space indent + ... + } + +Some points to note: + +- The open parenthesis is always on the same line as the function name. +- There is never a space between the function name and the open parenthesis. +- There is never a space between the parentheses and the parameters. +- The open curly brace is always on the next line. +- The close curly brace is always on the last line by itself. +- There should be a space between the close parenthesis and the open curly + brace. +- All parameters should be named, with identical names in the declaration and + implementation. +- All parameters should be aligned if possible. +- Default indentation is 2 spaces. +- Wrapped parameters have a 4 space indent. + + +Function Calls ~ + +On one line if it fits; otherwise, wrap arguments at the parenthesis. + +Function calls have the following format: > + + bool retval = do_something(argument1, argument2, argument3); + +If the arguments do not all fit on one line, they should be broken up onto +multiple lines, with each subsequent line aligned with the first argument. Do +not add spaces after the open paren or before the close paren: > + + bool retval = do_something(averyveryveryverylongargument1, + argument2, argument3); + +If the function has many arguments, consider having one per line if this makes +the code more readable: > + + bool retval = do_something(argument1, + argument2, + argument3, + argument4); + +Arguments may optionally all be placed on subsequent lines, with one line per +argument: > + + if (...) { + ... + ... + if (...) { + do_something( + argument1, // 4 space indent + argument2, + argument3, + argument4); + } + +In particular, this should be done if the function signature is so long that +it cannot fit within the maximum line length. + + +Braced Initializer Lists ~ + +Format a braced list exactly like you would format a function call in its +place but with one space after the `{` and one space before the `}` + +If the braced list follows a name (e.g. a type or variable name), format as if +the `{}` were the parentheses of a function call with that name. If there is +no name, assume a zero-length name. > + + struct my_struct m = { // Here, you could also break before {. + superlongvariablename1, + superlongvariablename2, + { short, interior, list }, + { interiorwrappinglist, + interiorwrappinglist2 } }; + + +Conditionals ~ + +Don't use spaces inside parentheses. Always use curly braces. > + + if (condition) { // no spaces inside parentheses + ... // 2 space indent. + } else if (...) { // The else goes on the same line as the closing brace. + ... + } else { + ... + } + +You must have a space between the `if` and the open parenthesis. You must also +have a space between the close parenthesis and the curly brace, if you're +using one. > + + if(condition) { // BAD: space missing after IF. + if (condition){ // BAD: space missing before {. + if (condition) { // GOOD: proper space after IF and before {. + + +Loops and Switch Statements ~ + +Annotate non-trivial fall-through between cases. Empty loop bodies should use +`{}` or `continue`. + +If not conditional on an enumerated value, switch statements should always +have a `default` case (in the case of an enumerated value, the compiler will +warn you if any values are not handled). If the default case should never +execute, simply `assert`: > + + switch (var) { + case 0: // 2 space indent + ... // 4 space indent + break; + case 1: + ... + break; + default: + assert(false); + } + +Empty loop bodies should use `{}` or `continue`, but not a single semicolon. > + + while (condition) { + // Repeat test until it returns false. + } + for (int i = 0; i < kSomeNumber; i++) {} // GOOD: empty body. + while (condition) continue; // GOOD: continue indicates no logic. + + while (condition); // BAD: looks like part of do/while loop. + +Pointer Expressions ~ + +No spaces around period or arrow. Pointer operators do not have trailing +spaces. + +The following are examples of correctly-formatted pointer and reference +expressions: > + + x = *p; + p = &x; + x = r.y; + x = r->y; + +Note that: + + - There are no spaces around the period or arrow when accessing a member. + - Pointer operators have no space after the * or &. + +When declaring a pointer variable or argument, place the asterisk adjacent to +the variable name: > + + char *c; + + char * c; // BAD: spaces on both sides of * + char* c; // BAD + + +Boolean Expressions ~ + +When you have a boolean expression that is longer than the standard line +length, keep operators at the start of the line. > + + if (this_one_thing > this_other_thing + && a_third_thing == a_fourth_thing + && yet_another && last_one) { + ... + } + +Also note that you should always use the punctuation operators, such as `&&` +and `~`, rather than the word operators, such as `and` and `compl`. + + +Return Values ~ + +Do not needlessly surround the `return` expression with parentheses. + +Use parentheses in `return expr`; only where you would use them in `x = +expr;`. > + + return result; + return (some_long_condition && another_condition); + + return (value); // You wouldn't write var = (value); + return(result); // return is not a function! + + +Preprocessor Directives ~ + +The hash mark that starts a preprocessor directive should always be at the +beginning of the line. + +Even when preprocessor directives are within the body of indented code, the +directives should start at the beginning of the line. + +Nested directives should add one spaces after the hash mark for each level of +indentation. + + // GOOD: directives at beginning of line > + if (lopsided_score) { + #if DISASTER_PENDING // Correct -- Starts at beginning of line + drop_everything(); + # if NOTIFY // One space after # + notify_client(); + # endif + #endif + BackToNormal(); + } + +< // BAD: indented directives > + if (lopsided_score) { + #if DISASTER_PENDING // Wrong! The "#if" should be at beginning of line + drop_everything(); + #endif // Wrong! Do not indent "#endif" + back_to_normal(); + } + + +Horizontal Whitespace ~ + +Use of horizontal whitespace depends on location. Never put trailing +whitespace at the end of a line. + + General ~ +> + if (x) { // Open braces should always have a space before them. + ... + } + int i = 0; // Semicolons usually have no space before them. + int x[] = { 0 }; // Spaces inside braces for braced-init-list. +< + + Variables ~ +> + int long_variable = 0; // Don't align assignments. + int i = 1; + + struct my_struct { // Exception: struct arrays. + const char *boy; + const char *girl; + int pos; + } my_variable[] = { + { "Mia", "Michael", 8 }, + { "Elizabeth", "Aiden", 10 }, + { "Emma", "Mason", 2 }, + }; +< + + Macros ~ +> + #define FI(x) \ // Don't align \'s in macro definitions. + foo(); \ + bar(); \ + ... +< + + Loops and Conditionals ~ +> + if (b) { // Space after the keyword in condition. + } else { // Spaces around else. + } + while (test) {} // There is usually no space inside parentheses. + for (; i < 5; i++) { // For loops always have a space after the + ... // semicolon and no a space before the + ... // semicolon. + } + switch (i) { + case 1: // No space before colon in a switch case. + ... + case 2: break; // Space after a colon if there's code after it. +< + + Operators ~ +> + x = 0; // Assignment operators always have spaces around + // them. + x = -5; // No spaces separating unary operators and their + x++; // arguments. + if (x && !y) + ... + v = w*x + y/z; // Use spaces to indicate operator precedence. + v = w * (x + z); // Parentheses should have no spaces inside them. + i = (int)d; // No spaces after a cast operator. +< + +Vertical Whitespace ~ + +Minimize use of vertical whitespace. + +This is more a principle than a rule: don't use blank lines when you don't +have to. In particular, don't put more than one or two blank lines between +functions, resist starting functions with a blank line, don't end functions +with a blank line, and be discriminating with your use of blank lines inside +functions. + +The basic principle is: The more code that fits on one screen, the easier it +is to follow and understand the control flow of the program. Of course, +readability can suffer from code being too dense as well as too spread out, so +use your judgment. But in general, minimize use of vertical whitespace. + + +============================================================================== +Parting Words + +The style guide is intended to make the code more readable. If you think you +must violate its rules for the sake of clarity, do it! But please add a note +to your pull request explaining your reasoning. + + + vim:tw=78:ts=8:et:ft=help:norl: diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 14e240783d..ac02bdae32 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2436,8 +2436,9 @@ getpos({expr}) List position of cursor, mark, etc. getqflist() List list of quickfix items getqflist({what}) Dict get specific quickfix list properties getreg([{regname} [, 1 [, {list}]]]) - String or List contents of register -getregtype([{regname}]) String type of register + String or List contents of a register +getreginfo([{regname}]) Dict information about a register +getregtype([{regname}]) String type of a register gettabinfo([{expr}]) List list of tab pages gettabvar({nr}, {varname} [, {def}]) any variable {varname} in tab {nr} or {def} @@ -5247,6 +5248,32 @@ getreg([{regname} [, 1 [, {list}]]]) *getreg()* If {regname} is not specified, |v:register| is used. +getreginfo([{regname}]) *getreginfo()* + Returns detailed information about register {regname} as a + Dictionary with the following entries: + regcontents List of lines contained in register + {regname}, like + |getreg|({regname}, 1, 1). + regtype the type of register {regname}, as in + |getregtype()|. + isunnamed Boolean flag, v:true if this register + is currently pointed to by the unnamed + register. + points_to for the unnamed register, gives the + single letter name of the register + currently pointed to (see |quotequote|). + For example, after deleting a line + with `dd`, this field will be "1", + which is the register that got the + deleted text. + + The {regname} argument is a string. If {regname} is invalid + or not set, an empty Dictionary will be returned. + If {regname} is not specified, |v:register| is used. + The returned Dictionary can be passed to |setreg()|. + + Can also be used as a |method|: > + GetRegname()->getreginfo() getregtype([{regname}]) *getregtype()* The result is a String, which is type of register {regname}. @@ -8435,8 +8462,8 @@ setreg({regname}, {value} [, {options}]) Set the register {regname} to {value}. The {regname} argument is a string. - {value} may be any value returned by |getreg()|, including - a |List|. + {value} may be any value returned by |getreg()| or + |getreginfo()|, including a |List| or |Dict|. If {options} contains "a" or {regname} is upper case, then the value is appended. @@ -8466,9 +8493,13 @@ setreg({regname}, {value} [, {options}]) :call setreg(v:register, @*) :call setreg('*', @%, 'ac') :call setreg('a', "1\n2\n3", 'b5') + :call setreg('"', { 'points_to': 'a'}) < This example shows using the functions to save and restore a register: > + :let var_a = getreginfo() + :call setreg('a', var_a) +< or: > :let var_a = getreg('a', 1, 1) :let var_amode = getregtype('a') .... diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 5fddadcf01..5d70834ddc 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1025,6 +1025,7 @@ Various: *various-functions* undotree() return the state of the undo tree getreg() get contents of a register + getreginfo() get information about a register getregtype() get type of a register setreg() set contents and type of a register reg_executing() return the name of the register being executed diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 961e071273..3f41ee5df8 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -249,7 +249,7 @@ end ---@private local function diagnostic_lines(diagnostics) if not diagnostics then - return + return {} end local diagnostics_by_line = {} @@ -379,7 +379,7 @@ end ---@param diagnostics table: The diagnostics to display ---@return table {popup_bufnr, win_id} local function show_diagnostics(opts, diagnostics) - if vim.tbl_isempty(diagnostics) then + if not diagnostics or vim.tbl_isempty(diagnostics) then return end local lines = {} diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index c2f2b870f7..624f8b5462 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -143,12 +143,14 @@ M['textDocument/codeAction'] = function(_, result, ctx) if action.edit then util.apply_workspace_edit(action.edit) end - local command = type(action.command) == 'table' and action.command or action - local fn = vim.lsp.commands[command.command] - if fn then - fn(command, ctx) - else - buf.execute_command(command) + if action.command then + local command = type(action.command) == 'table' and action.command or action + local fn = vim.lsp.commands[command.command] + if fn then + fn(command, ctx) + else + buf.execute_command(command) + end end end diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua index 11ad8eb9ef..98f9da246c 100644 --- a/scripts/lintcommit.lua +++ b/scripts/lintcommit.lua @@ -91,7 +91,7 @@ local function validate_commit(commit_message) -- Check that description doesn't end with a period if vim.endswith(after_colon, ".") then - return [[Description ends with a period (\".\").]] + return [[Description ends with a period (".").]] end -- Check that description has exactly one whitespace after colon, followed by diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index aa27c94f29..904ff81700 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -373,13 +373,13 @@ run_analysis() {( analyze \ --lic-file PVS-Studio.lic \ --threads "$(get_jobs_num)" \ - --exclude-path src/nvim/xdiff \ + --exclude-path src/xdiff \ --output-file PVS-studio.log \ --file build/compile_commands.json \ --sourcetree-root . || true rm -rf PVS-studio.{xml,err,tsk,html.d} - local plog_args="PVS-studio.log --srcRoot . --excludedCodes V011,V1042" + local plog_args="PVS-studio.log --srcRoot . --excludedCodes V011,V1042,V1051,V1074" plog-converter $plog_args --renderTypes xml --output PVS-studio.xml plog-converter $plog_args --renderTypes errorfile --output PVS-studio.err plog-converter $plog_args --renderTypes tasklist --output PVS-studio.tsk diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 8973f8fef6..0ef2776263 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1415,6 +1415,10 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// - end_col : ending col of the mark, 0-based exclusive. /// - hl_group : name of the highlight group used to highlight /// this mark. +/// - hl_eol : when true, for a multiline highlight covering the +/// EOL of a line, continue the highlight for the rest +/// of the screen line (just like for diff and +/// cursorline highlight). /// - virt_text : virtual text to link to this mark. /// A list of [text, highlight] tuples, each representing a /// text chunk with specified highlight. `highlight` element @@ -1442,10 +1446,28 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// default /// - "combine": combine with background text color /// - "blend": blend with background text color. -/// - hl_eol : when true, for a multiline highlight covering the -/// EOL of a line, continue the highlight for the rest -/// of the screen line (just like for diff and -/// cursorline highlight). +/// +/// - virt_lines : virtual lines to add next to this mark +/// This should be an array over lines, where each line in +/// turn is an array over [text, highlight] tuples. In +/// general, buffer and window options do not affect the +/// display of the text. In particular 'wrap' +/// and 'linebreak' options do not take effect, so +/// the number of extra screen lines will always match +/// the size of the array. However the 'tabstop' buffer +/// option is still used for hard tabs. By default lines are +/// placed below the buffer line containing the mark. +/// +/// Note: currently virtual lines are limited to one block +/// per buffer. Thus setting a new mark disables any previous +/// `virt_lines` decoration. However plugins should not rely +/// on this behaviour, as this limitation is planned to be +/// removed. +/// +/// - virt_lines_above: place virtual lines above instead. +/// - virt_lines_leftcol: Place extmarks in the leftmost +/// column of the window, bypassing +/// sign and number columns. /// /// - ephemeral : for use with |nvim_set_decoration_provider| /// callbacks. The mark will only be used for the current @@ -1487,6 +1509,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer bool end_right_gravity = false; bool end_gravity_set = false; + VirtLines virt_lines = KV_INITIAL_VALUE; + bool virt_lines_above = false; + bool virt_lines_leftcol = false; + for (size_t i = 0; i < opts.size; i++) { String k = opts.items[i].key; Object *v = &opts.items[i].value; @@ -1584,6 +1610,36 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer if (ERROR_SET(err)) { goto error; } + } else if (strequal("virt_lines", k.data)) { + if (v->type != kObjectTypeArray) { + api_set_error(err, kErrorTypeValidation, + "virt_lines is not an Array"); + goto error; + } + Array a = v->data.array; + for (size_t j = 0; j < a.size; j++) { + if (a.items[j].type != kObjectTypeArray) { + api_set_error(err, kErrorTypeValidation, + "virt_text_line item is not an Array"); + goto error; + } + int dummig; + VirtText jtem = parse_virt_text(a.items[j].data.array, err, &dummig); + kv_push(virt_lines, jtem); + if (ERROR_SET(err)) { + goto error; + } + } + } else if (strequal("virt_lines_above", k.data)) { + virt_lines_above = api_object_to_bool(*v, "virt_lines_above", false, err); + if (ERROR_SET(err)) { + goto error; + } + } else if (strequal("virt_lines_leftcol", k.data)) { + virt_lines_leftcol = api_object_to_bool(*v, "virt_lines_leftcol", false, err); + if (ERROR_SET(err)) { + goto error; + } } else if (strequal("hl_eol", k.data)) { decor.hl_eol = api_object_to_bool(*v, "hl_eol", false, err); if (ERROR_SET(err)) { @@ -1721,9 +1777,23 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer goto error; } - id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col, - line2, col2, d, right_gravity, - end_right_gravity, kExtmarkNoUndo); + if (kv_size(virt_lines) && buf->b_virt_line_mark) { + mtpos_t pos = marktree_lookup(buf->b_marktree, buf->b_virt_line_mark, NULL); + clear_virt_lines(buf, pos.row); // handles pos.row == -1 + } + + uint64_t mark = extmark_set(buf, (uint64_t)ns_id, &id, (int)line, (colnr_T)col, + line2, col2, d, right_gravity, + end_right_gravity, kExtmarkNoUndo); + + if (kv_size(virt_lines)) { + buf->b_virt_lines = virt_lines; + buf->b_virt_line_mark = mark; + buf->b_virt_line_pos = -1; + buf->b_virt_line_above = virt_lines_above; + buf->b_virt_line_leftcol = virt_lines_leftcol; + redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, line+1+(virt_lines_above?0:1))); + } } return (Integer)id; @@ -1827,7 +1897,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In end_line++; } - extmark_set(buf, ns, 0, + extmark_set(buf, ns, NULL, (int)line, (colnr_T)col_start, end_line, (colnr_T)col_end, decor_hl(hl_id), true, false, kExtmarkNoUndo); diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index 21b9db85c0..332fc0ba96 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -150,7 +150,7 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, A decor->virt_text = virt_text; decor->virt_text_width = width; - extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, true, + extmark_set(buf, ns_id, NULL, (int)line, 0, -1, -1, decor, true, false, kExtmarkNoUndo); return src_id; } diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 541793e528..193f1dd572 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1413,8 +1413,10 @@ static void set_option_value_for(char *key, int numval, char *stringval, int opt switch (opt_type) { case SREQ_WIN: - if (switch_win(&save_curwin, &save_curtab, (win_T *)from, - win_find_tabpage((win_T *)from), false) == FAIL) { + if (switch_win_noblock(&save_curwin, &save_curtab, (win_T *)from, + win_find_tabpage((win_T *)from), true) + == FAIL) { + restore_win_noblock(save_curwin, save_curtab, true); if (try_end(err)) { return; } @@ -1424,7 +1426,7 @@ static void set_option_value_for(char *key, int numval, char *stringval, int opt return; } set_option_value_err(key, numval, stringval, opt_flags, err); - restore_win(save_curwin, save_curtab, true); + restore_win_noblock(save_curwin, save_curtab, true); break; case SREQ_BUF: aucmd_prepbuf(&aco, (buf_T *)from); @@ -1625,7 +1627,7 @@ VirtText parse_virt_text(Array chunks, Error *err, int *width) } } - char *text = transstr(str.size > 0 ? str.data : ""); // allocates + char *text = transstr(str.size > 0 ? str.data : "", false); // allocates w += (int)mb_string2cells((char_u *)text); kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id })); diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 4c502b53d4..67b2b8954d 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -956,10 +956,11 @@ static int do_autocmd_event(event_T event, char_u *pat, bool once, int nested, c return OK; } -// Implementation of ":doautocmd [group] event [fname]". -// Return OK for success, FAIL for failure; -int do_doautocmd(char_u *arg, bool do_msg, // give message for no matching autocmds? - bool *did_something) +/// Implementation of ":doautocmd [group] event [fname]". +/// Return OK for success, FAIL for failure; +/// +/// @param do_msg give message for no matching autocmds? +int do_doautocmd(char_u *arg, bool do_msg, bool *did_something) { char_u *fname; int nothing_done = true; @@ -1916,8 +1917,8 @@ char_u *get_augroup_name(expand_T *xp, int idx) return (char_u *)AUGROUP_NAME(idx); } -char_u *set_context_in_autocmd(expand_T *xp, char_u *arg, int doautocmd // true for :doauto*, false for :autocmd - ) +/// @param doautocmd true for :doauto*, false for :autocmd +char_u *set_context_in_autocmd(expand_T *xp, char_u *arg, int doautocmd) { char_u *p; int group; diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 2b5325a917..54b5f8283f 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -65,6 +65,7 @@ #include "nvim/os/time.h" #include "nvim/os_unix.h" #include "nvim/path.h" +#include "nvim/plines.h" #include "nvim/quickfix.h" #include "nvim/regexp.h" #include "nvim/screen.h" @@ -98,13 +99,15 @@ typedef enum { kBffInitChangedtick = 2, } BufFreeFlags; -// Read data from buffer for retrying. -static int read_buffer(int read_stdin, // read file from stdin, otherwise fifo - exarg_T *eap, // for forced 'ff' and 'fenc' or NULL - int flags) // extra flags for readfile() +/// Read data from buffer for retrying. +/// +/// @param read_stdin read file from stdin, otherwise fifo +/// @param eap for forced 'ff' and 'fenc' or NULL +/// @param flags extra flags for readfile() +static int read_buffer(int read_stdin, exarg_T *eap, int flags) { - int retval = OK; - linenr_T line_count; + int retval = OK; + linenr_T line_count; // // Read from the buffer which the text is already filled in and append at @@ -146,16 +149,18 @@ static int read_buffer(int read_stdin, // read file from stdin, otherwis return retval; } -// Open current buffer, that is: open the memfile and read the file into -// memory. -// Return FAIL for failure, OK otherwise. -int open_buffer(int read_stdin, // read file from stdin - exarg_T *eap, // for forced 'ff' and 'fenc' or NULL - int flags // extra flags for readfile() - ) +/// Open current buffer, that is: open the memfile and read the file into +/// memory. +/// +/// @param read_stdin read file from stdin +/// @param eap for forced 'ff' and 'fenc' or NULL +/// @param flags extra flags for readfile() +/// +/// @return FAIL for failure, OK otherwise. +int open_buffer(int read_stdin, exarg_T *eap, int flags) { int retval = OK; - bufref_T old_curbuf; + bufref_T old_curbuf; long old_tw = curbuf->b_p_tw; int read_fifo = false; @@ -816,6 +821,7 @@ static void free_buffer_stuff(buf_T *buf, int free_flags) uc_clear(&buf->b_ucmds); // clear local user commands buf_delete_signs(buf, (char_u *)"*"); // delete any signs extmark_free_all(buf); // delete any extmarks + clear_virt_lines(buf, -1); map_clear_int(buf, MAP_ALL_MODES, true, false); // clear local mappings map_clear_int(buf, MAP_ALL_MODES, true, true); // clear local abbrevs XFREE_CLEAR(buf->b_start_fenc); @@ -939,23 +945,22 @@ void handle_swap_exists(bufref_T *old_curbuf) swap_exists_action = SEA_NONE; // -V519 } -/* - * do_bufdel() - delete or unload buffer(s) - * - * addr_count == 0: ":bdel" - delete current buffer - * addr_count == 1: ":N bdel" or ":bdel N [N ..]" - first delete - * buffer "end_bnr", then any other arguments. - * addr_count == 2: ":N,N bdel" - delete buffers in range - * - * command can be DOBUF_UNLOAD (":bunload"), DOBUF_WIPE (":bwipeout") or - * DOBUF_DEL (":bdel") - * - * Returns error message or NULL - */ -char_u *do_bufdel(int command, char_u *arg, // pointer to extra arguments - int addr_count, int start_bnr, // first buffer number in a range - int end_bnr, // buffer nr or last buffer nr in a range - int forceit) +/// do_bufdel() - delete or unload buffer(s) +/// +/// addr_count == 0: ":bdel" - delete current buffer +/// addr_count == 1: ":N bdel" or ":bdel N [N ..]" - first delete +/// buffer "end_bnr", then any other arguments. +/// addr_count == 2: ":N,N bdel" - delete buffers in range +/// +/// command can be DOBUF_UNLOAD (":bunload"), DOBUF_WIPE (":bwipeout") or +/// DOBUF_DEL (":bdel") +/// +/// @param arg pointer to extra arguments +/// @param start_bnr first buffer number in a range +/// @param end_bnr buffer nr or last buffer nr in a range +/// +/// @return error message or NULL +char_u *do_bufdel(int command, char_u *arg, int addr_count, int start_bnr, int end_bnr, int forceit) { int do_current = 0; // delete current buffer? int deleted = 0; // number of buffers deleted @@ -1097,26 +1102,26 @@ static int empty_curbuf(int close_others, int forceit, int action) return retval; } -/* - * Implementation of the commands for the buffer list. - * - * action == DOBUF_GOTO go to specified buffer - * action == DOBUF_SPLIT split window and go to specified buffer - * action == DOBUF_UNLOAD unload specified buffer(s) - * action == DOBUF_DEL delete specified buffer(s) from buffer list - * action == DOBUF_WIPE delete specified buffer(s) really - * - * start == DOBUF_CURRENT go to "count" buffer from current buffer - * start == DOBUF_FIRST go to "count" buffer from first buffer - * start == DOBUF_LAST go to "count" buffer from last buffer - * start == DOBUF_MOD go to "count" modified buffer from current buffer - * - * Return FAIL or OK. - */ -int do_buffer(int action, int start, int dir, // FORWARD or BACKWARD - int count, // buffer number or number of buffers - int forceit // true for :...! - ) + +/// Implementation of the commands for the buffer list. +/// +/// action == DOBUF_GOTO go to specified buffer +/// action == DOBUF_SPLIT split window and go to specified buffer +/// action == DOBUF_UNLOAD unload specified buffer(s) +/// action == DOBUF_DEL delete specified buffer(s) from buffer list +/// action == DOBUF_WIPE delete specified buffer(s) really +/// +/// start == DOBUF_CURRENT go to "count" buffer from current buffer +/// start == DOBUF_FIRST go to "count" buffer from first buffer +/// start == DOBUF_LAST go to "count" buffer from last buffer +/// start == DOBUF_MOD go to "count" modified buffer from current buffer +/// +/// @param dir FORWARD or BACKWARD +/// @param count buffer number or number of buffers +/// @param forceit true for :...! +/// +/// @return FAIL or OK. +int do_buffer(int action, int start, int dir, int count, int forceit) { buf_T *buf; buf_T *bp; @@ -2154,11 +2159,13 @@ static buf_T *buflist_findname_file_id(char_u *ffname, FileID *file_id, bool fil /// Find file in buffer list by a regexp pattern. /// Return fnum of the found buffer. /// Return < 0 for error. -int buflist_findpat(const char_u *pattern, const char_u *pattern_end, // pointer to first char after pattern - bool unlisted, // find unlisted buffers - bool diffmode, // find diff-mode buffers only - bool curtab_only // find buffers in current tab only - ) +/// +/// @param pattern_end pointer to first char after pattern +/// @param unlisted find unlisted buffers +/// @param diffmode find diff-mode buffers only +/// @param curtab_only find buffers in current tab only +int buflist_findpat(const char_u *pattern, const char_u *pattern_end, bool unlisted, bool diffmode, + bool curtab_only) FUNC_ATTR_NONNULL_ARG(1) { int match = -1; @@ -2466,14 +2473,14 @@ buf_T *buflist_findnr(int nr) return handle_get_buffer((handle_T)nr); } -/* - * Get name of file 'n' in the buffer list. - * When the file has no name an empty string is returned. - * home_replace() is used to shorten the file name (used for marks). - * Returns a pointer to allocated memory, of NULL when failed. - */ -char_u *buflist_nr2name(int n, int fullname, int helptail // for help buffers return tail only - ) +/// Get name of file 'n' in the buffer list. +/// When the file has no name an empty string is returned. +/// home_replace() is used to shorten the file name (used for marks). +/// +/// @param helptail for help buffers return tail only +/// +/// @return a pointer to allocated memory, of NULL when failed. +char_u *buflist_nr2name(int n, int fullname, int helptail) { buf_T *buf; @@ -2800,13 +2807,14 @@ int buflist_name_nr(int fnum, char_u **fname, linenr_T *lnum) return OK; } -// Set the file name for "buf" to "ffname_arg", short file name to -// "sfname_arg". -// The file name with the full path is also remembered, for when :cd is used. -// Returns FAIL for failure (file name already in use by other buffer) -// OK otherwise. -int setfname(buf_T *buf, char_u *ffname_arg, char_u *sfname_arg, bool message // give message when buffer already exists - ) +/// Set the file name for "buf" to "ffname_arg", short file name to +/// "sfname_arg". +/// The file name with the full path is also remembered, for when :cd is used. +/// +/// @param message give message when buffer already exists +/// +/// @return FAIL for failure (file name already in use by other buffer) OK otherwise. +int setfname(buf_T *buf, char_u *ffname_arg, char_u *sfname_arg, bool message) { char_u *ffname = ffname_arg; char_u *sfname = sfname_arg; @@ -2934,12 +2942,11 @@ buf_T *setaltfname(char_u *ffname, char_u *sfname, linenr_T lnum) return buf; } -/* - * Get alternate file name for current window. - * Return NULL if there isn't any, and give error message if requested. - */ -char_u *getaltfname(bool errmsg // give error message - ) +/// Get alternate file name for current window. +/// Return NULL if there isn't any, and give error message if requested. +/// +/// @param errmsg give error message +char_u *getaltfname(bool errmsg) { char_u *fname; linenr_T dummy; @@ -3078,11 +3085,10 @@ static bool buf_same_file_id(buf_T *buf, FileID *file_id) return buf->file_id_valid && os_fileid_equal(&(buf->file_id), file_id); } -/* - * Print info about the current buffer. - */ -void fileinfo(int fullname, // when non-zero print full path - int shorthelp, int dont_truncate) +/// Print info about the current buffer. +/// +/// @param fullname when non-zero print full path +void fileinfo(int fullname, int shorthelp, int dont_truncate) { char_u *name; int n; @@ -3112,12 +3118,13 @@ void fileinfo(int fullname, // when non-zero print full path (size_t)(IOSIZE - (p - buffer)), true); } + bool dontwrite = bt_dontwrite(curbuf); vim_snprintf_add((char *)buffer, IOSIZE, "\"%s%s%s%s%s%s", curbufIsChanged() ? (shortmess(SHM_MOD) ? " [+]" : _(" [Modified]")) : " ", - (curbuf->b_flags & BF_NOTEDITED) && !bt_dontwrite(curbuf) + (curbuf->b_flags & BF_NOTEDITED) && !dontwrite ? _("[Not edited]") : "", - (curbuf->b_flags & BF_NEW) && !bt_dontwrite(curbuf) + (curbuf->b_flags & BF_NEW) && !dontwrite ? new_file_message() : "", (curbuf->b_flags & BF_READERR) ? _("[Read errors]") : "", @@ -3257,7 +3264,7 @@ void maketitle(void) buf_p += MIN(size, SPACE_FOR_FNAME); } else { buf_p += transstr_buf((const char *)path_tail(curbuf->b_fname), - buf_p, SPACE_FOR_FNAME + 1); + buf_p, SPACE_FOR_FNAME + 1, true); } switch (bufIsChanged(curbuf) @@ -3306,7 +3313,7 @@ void maketitle(void) // room for the server name. When there is no room (very long // file name) use (...). if ((size_t)(buf_p - buf) < SPACE_FOR_DIR) { - char *const tbuf = transstr(buf_p); + char *const tbuf = transstr(buf_p, true); const size_t free_space = SPACE_FOR_DIR - (size_t)(buf_p - buf) + 1; const size_t dir_len = xstrlcpy(buf_p, tbuf, free_space); buf_p += MIN(dir_len, free_space - 1); @@ -4652,7 +4659,7 @@ void get_rel_pos(win_T *wp, char_u *buf, int buflen) long below; // number of lines below window above = wp->w_topline - 1; - above += diff_check_fill(wp, wp->w_topline) - wp->w_topfill; + above += win_get_fill(wp, wp->w_topline) - wp->w_topfill; if (wp->w_topline == 1 && wp->w_topfill >= 1) { // All buffer lines are displayed and there is an indication // of filler lines, that can be considered seeing all lines. @@ -4750,12 +4757,11 @@ char_u *alist_name(aentry_T *aep) return bp->b_fname; } -/* - * do_arg_all(): Open up to 'count' windows, one for each argument. - */ -void do_arg_all(int count, int forceit, // hide buffers in current windows - int keep_tabs // keep current tabs, for ":tab drop file" - ) +/// do_arg_all(): Open up to 'count' windows, one for each argument. +/// +/// @param forceit hide buffers in current windows +/// @param keep_tabs keep current tabs, for ":tab drop file" +void do_arg_all(int count, int forceit, int keep_tabs) { char_u *opened; // Array of weight for which args are open: // 0: not opened @@ -5253,12 +5259,11 @@ void do_modelines(int flags) entered--; } -/* - * chk_modeline() - check a single line for a mode string - * Return FAIL if an error encountered. - */ -static int chk_modeline(linenr_T lnum, int flags // Same as for do_modelines(). - ) +/// chk_modeline() - check a single line for a mode string +/// Return FAIL if an error encountered. +/// +/// @param flags Same as for do_modelines(). +static int chk_modeline(linenr_T lnum, int flags) { char_u *s; char_u *e; @@ -5630,13 +5635,12 @@ bool buf_contents_changed(buf_T *buf) return differ; } -/* - * Wipe out a buffer and decrement the last buffer number if it was used for - * this buffer. Call this to wipe out a temp buffer that does not contain any - * marks. - */ -void wipe_buffer(buf_T *buf, bool aucmd // When true trigger autocommands. - ) +/// Wipe out a buffer and decrement the last buffer number if it was used for +/// this buffer. Call this to wipe out a temp buffer that does not contain any +/// marks. +/// +/// @param aucmd When true trigger autocommands. +void wipe_buffer(buf_T *buf, bool aucmd) { if (!aucmd) { // Don't trigger BufDelete autocommands here. diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index ba2bcd7223..0264a60117 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -868,6 +868,12 @@ struct file_buffer { Map(uint64_t, ExtmarkItem) b_extmark_index[1]; Map(uint64_t, ExtmarkNs) b_extmark_ns[1]; // extmark namespaces + VirtLines b_virt_lines; + uint64_t b_virt_line_mark; + int b_virt_line_pos; + bool b_virt_line_above; + bool b_virt_line_leftcol; + // array of channel_id:s which have asked to receive updates for this // buffer. kvec_t(uint64_t) update_channels; diff --git a/src/nvim/change.c b/src/nvim/change.c index ccceb0e320..4ac5edeaa9 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -461,15 +461,15 @@ void changed_lines_buf(buf_T *buf, linenr_T lnum, linenr_T lnume, long xtra) /// When only inserting lines, "lnum" and "lnume" are equal. /// Takes care of calling changed() and updating b_mod_*. /// Careful: may trigger autocommands that reload the buffer. -void changed_lines(linenr_T lnum, // first line with change - colnr_T col, // column in first line with change - linenr_T lnume, // line below last changed line - long xtra, // number of extra lines (negative when deleting) - bool do_buf_event // some callers like undo/redo call changed_lines() - // and then increment changedtick *again*. This flag - // allows these callers to send the nvim_buf_lines_event - // events after they're done modifying changedtick. - ) +/// +/// @param lnum first line with change +/// @param col column in first line with change +/// @param lnume line below last changed line +/// @param xtra number of extra lines (negative when deleting) +/// @param do_buf_event some callers like undo/redo call changed_lines() and +/// then increment changedtick *again*. This flag allows these callers to send +/// the nvim_buf_lines_event events after they're done modifying changedtick. +void changed_lines(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra, bool do_buf_event) { changed_lines_buf(curbuf, lnum, lnume, xtra); @@ -950,9 +950,10 @@ int copy_indent(int size, char_u *src) /// "second_line_indent": indent for after ^^D in Insert mode or if flag /// OPENLINE_COM_LIST /// +/// @param dir FORWARD or BACKWARD +/// /// @return true on success, false on failure -int open_line(int dir, // FORWARD or BACKWARD - int flags, int second_line_indent) +int open_line(int dir, int flags, int second_line_indent) { char_u *next_line = NULL; // copy of the next line char_u *p_extra = NULL; // what goes to next line diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 0ad7dddd33..f899ebf57c 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -310,7 +310,7 @@ void trans_characters(char_u *buf, int bufsize) /// /// @return number of bytes needed to hold a translation of `s`, NUL byte not /// included. -size_t transstr_len(const char *const s) +size_t transstr_len(const char *const s, bool untab) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { const char *p = s; @@ -331,6 +331,9 @@ size_t transstr_len(const char *const s) } } p += l; + } else if (*p == TAB && !untab) { + len += 1; + p++; } else { const int b2c_l = byte2cells((uint8_t)(*p++)); // Illegal byte sequence may occupy up to 4 characters. @@ -346,9 +349,10 @@ size_t transstr_len(const char *const s) /// @param[out] buf Buffer to which result should be saved. /// @param[in] len Buffer length. Resulting string may not occupy more then /// len - 1 bytes (one for trailing NUL byte). +/// @param[in] untab remove tab characters /// /// @return length of the resulting string, without the NUL byte. -size_t transstr_buf(const char *const s, char *const buf, const size_t len) +size_t transstr_buf(const char *const s, char *const buf, const size_t len, bool untab) FUNC_ATTR_NONNULL_ALL { const char *p = s; @@ -379,6 +383,8 @@ size_t transstr_buf(const char *const s, char *const buf, const size_t len) } } p += l; + } else if (*p == TAB && !untab) { + *buf_p++ = *p++; } else { const char *const tb = (const char *)transchar_byte((uint8_t)(*p++)); const size_t tb_len = strlen(tb); @@ -401,14 +407,14 @@ size_t transstr_buf(const char *const s, char *const buf, const size_t len) /// @param[in] s String to replace characters from. /// /// @return [allocated] translated string -char *transstr(const char *const s) +char *transstr(const char *const s, bool untab) FUNC_ATTR_NONNULL_RET { // Compute the length of the result, taking account of unprintable // multi-byte characters. - const size_t len = transstr_len((const char *)s) + 1; + const size_t len = transstr_len((const char *)s, untab) + 1; char *const buf = xmalloc(len); - transstr_buf(s, buf, len); + transstr_buf(s, buf, len, untab); return buf; } diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index 2eced03c03..e334fd166e 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -93,10 +93,10 @@ int coladvance(colnr_T wcol) return rc; } -static int coladvance2(pos_T *pos, bool addspaces, // change the text to achieve our goal? - bool finetune, // change char offset for the exact column - colnr_T wcol_arg // column to move to (can be negative) - ) +/// @param addspaces change the text to achieve our goal? +/// @param finetune change char offset for the exact column +/// @param wcol_arg column to move to (can be negative) +static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_arg) { colnr_T wcol = wcol_arg; int idx; diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index a5dd4cd485..0ddf163176 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -718,10 +718,11 @@ void ex_breaklist(exarg_T *eap) /// Find a breakpoint for a function or sourced file. /// Returns line number at which to break; zero when no matching breakpoint. -linenr_T dbg_find_breakpoint(bool file, // true for a file, false for a function - char_u *fname, // file or function name - linenr_T after // after this line number - ) +/// +/// @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) { return debuggy_find(file, fname, after, &dbg_breakp, NULL); } @@ -738,12 +739,13 @@ bool has_profiling(bool file, char_u *fname, bool *fp) } /// Common code for dbg_find_breakpoint() and has_profiling(). -static linenr_T debuggy_find(bool file, // true for a file, false for a function - char_u *fname, // file or function name - linenr_T after, // after this line number - garray_T *gap, // either &dbg_breakp or &prof_ga - bool *fp // if not NULL: return forceit - ) +/// +/// @param file true for a file, false for a function +/// @param fname file or function name +/// @param after after this line number +/// @param gap either &dbg_breakp or &prof_ga +/// @param fp if not NULL: return forceit +static linenr_T debuggy_find(bool file, char_u *fname, linenr_T after, garray_T *gap, bool *fp) { struct debuggy *bp; linenr_T lnum = 0; diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 0f21b47261..7e2b6a666e 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -59,7 +59,7 @@ void bufhl_add_hl_pos_offset(buf_T *buf, int src_id, int hl_id, lpos_T pos_start hl_start = pos_start.col + offset; hl_end = pos_end.col + offset; } - (void)extmark_set(buf, (uint64_t)src_id, 0, + (void)extmark_set(buf, (uint64_t)src_id, NULL, (int)lnum-1, hl_start, (int)lnum-1+end_off, hl_end, decor, true, false, kExtmarkNoUndo); } @@ -412,3 +412,35 @@ void decor_free_all_mem(void) } kv_destroy(decor_providers); } + + +int decor_virtual_lines(win_T *wp, linenr_T lnum) +{ + buf_T *buf = wp->w_buffer; + if (!buf->b_virt_line_mark) { + return 0; + } + if (buf->b_virt_line_pos < 0) { + mtpos_t pos = marktree_lookup(buf->b_marktree, buf->b_virt_line_mark, NULL); + if (pos.row < 0) { + buf->b_virt_line_mark = 0; + } + buf->b_virt_line_pos = pos.row + (buf->b_virt_line_above ? 0 : 1); + } + + return (lnum-1 == buf->b_virt_line_pos) ? (int)kv_size(buf->b_virt_lines) : 0; +} + +void clear_virt_lines(buf_T *buf, int row) +{ + if (row > -1) { + redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, + row+1+(buf->b_virt_line_above?0:1))); + } + for (size_t i = 0; i < kv_size(buf->b_virt_lines); i++) { + clear_virttext(&kv_A(buf->b_virt_lines, i)); + } + kv_destroy(buf->b_virt_lines); // re-initializes + buf->b_virt_line_pos = -1; + buf->b_virt_line_mark = 0; +} diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h index 28dabeeada..35f5af87ed 100644 --- a/src/nvim/decoration.h +++ b/src/nvim/decoration.h @@ -7,14 +7,6 @@ // actual Decoration data is in extmark_defs.h -typedef struct { - char *text; - int hl_id; -} VirtTextChunk; - -typedef kvec_t(VirtTextChunk) VirtText; -#define VIRTTEXT_EMPTY ((VirtText)KV_INITIAL_VALUE) - typedef uint16_t DecorPriority; #define DECOR_PRIORITY_BASE 0x1000 diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 1d70145209..5c43b2498e 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -73,21 +73,21 @@ static TriState diff_a_works = kNone; // used for diff input typedef struct { char_u *din_fname; // used for external diff - mmfile_t din_mmfile; // used for internal diff + mmfile_t din_mmfile; // used for internal diff } diffin_T; // used for diff result typedef struct { char_u *dout_fname; // used for external diff - garray_T dout_ga; // used for internal diff + garray_T dout_ga; // used for internal diff } diffout_T; // two diff inputs and one result typedef struct { - diffin_T dio_orig; // original file input - diffin_T dio_new; // new file input - diffout_T dio_diff; // diff result - int dio_internal; // using internal diff + diffin_T dio_orig; // original file input + diffin_T dio_new; // new file input + diffout_T dio_diff; // diff result + int dio_internal; // using internal diff } diffio_T; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -702,9 +702,9 @@ static void clear_diffout(diffout_T *dout) /// @return FAIL for failure. static int diff_write_buffer(buf_T *buf, diffin_T *din) { - linenr_T lnum; + linenr_T lnum; char_u *s; - long len = 0; + long len = 0; char_u *ptr; // xdiff requires one big block of memory with all the text. @@ -732,7 +732,7 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din) for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) { for (s = ml_get_buf(buf, lnum, false); *s != NUL; ) { if (diff_flags & DIFF_ICASE) { - char_u cbuf[MB_MAXBYTES + 1]; + char_u cbuf[MB_MAXBYTES + 1]; // xdiff doesn't support ignoring case, fold-case the text. int c = PTR2CHAR(s); @@ -787,10 +787,10 @@ static int diff_write(buf_T *buf, diffin_T *din) /// @param dio /// @param idx_orig /// @param eap can be NULL -static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap) +static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap) { buf_T *buf; - int idx_new; + int idx_new; if (dio->dio_internal) { ga_init(&dio->dio_diff.dout_ga, sizeof(char *), 1000); @@ -928,7 +928,7 @@ void ex_diffupdate(exarg_T *eap) } // Only use the internal method if it did not fail for one of the buffers. - diffio_T diffio; + diffio_T diffio; memset(&diffio, 0, sizeof(diffio)); diffio.dio_internal = diff_internal() && !diff_internal_failed(); @@ -1044,9 +1044,9 @@ static int check_external_diff(diffio_T *diffio) /// static int diff_file_internal(diffio_T *diffio) { - xpparam_t param; - xdemitconf_t emit_cfg; - xdemitcb_t emit_cb; + xpparam_t param; + xdemitconf_t emit_cfg; + xdemitcb_t emit_cb; memset(¶m, 0, sizeof(param)); memset(&emit_cfg, 0, sizeof(emit_cfg)); @@ -1985,26 +1985,6 @@ static int diff_cmp(char_u *s1, char_u *s2) return 0; } -/// Return the number of filler lines above "lnum". -/// -/// @param wp -/// @param lnum -/// -/// @return Number of filler lines above lnum -int diff_check_fill(win_T *wp, linenr_T lnum) -{ - // be quick when there are no filler lines - if (!(diff_flags & DIFF_FILLER)) { - return 0; - } - int n = diff_check(wp, lnum); - - if (n <= 0) { - return 0; - } - return n; -} - /// Set the topline of "towin" to match the position in "fromwin", so that they /// show the same diff'ed lines. /// @@ -2030,6 +2010,7 @@ void diff_set_topline(win_T *fromwin, win_T *towin) } towin->w_topfill = 0; + // search for a change that includes "lnum" in the list of diffblocks. for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) { if (lnum <= dp->df_lnum[fromidx] + dp->df_count[fromidx]) { @@ -2255,6 +2236,13 @@ bool diffopt_closeoff(void) return (diff_flags & DIFF_CLOSE_OFF) != 0; } +// Return true if 'diffopt' contains "filler". +bool diffopt_filler(void) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return (diff_flags & DIFF_FILLER) != 0; +} + /// Find the difference within a changed line. /// /// @param wp window whose current buffer to check @@ -3033,8 +3021,8 @@ static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, li long *count_new) { char_u *p; - long f1, l1, f2, l2; - int difftype; + long f1, l1, f2, l2; + int difftype; // The line must be one of three formats: // change: {first}[,{last}]c{first}[,{last}] @@ -3088,7 +3076,7 @@ static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_ori linenr_T *lnum_new, long *count_new) { char_u *p; - long oldline, oldcount, newline, newcount; + long oldline, oldcount, newline, newcount; // Parse unified diff hunk header: // @@ -oldline,oldcount +newline,newcount @@ diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 20dc3cd06b..085bbc2409 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -147,7 +147,7 @@ struct compl_S { compl_T *cp_prev; char_u *cp_str; // matched text char_u *(cp_text[CPT_COUNT]); // text for the menu - typval_T cp_user_data; + typval_T cp_user_data; char_u *cp_fname; // file containing the match, allocated when // cp_flags has CP_FREE_FNAME int cp_flags; // CP_ values @@ -3344,12 +3344,10 @@ static char_u *ins_compl_mode(void) */ static int ins_compl_bs(void) { - char_u *line; - char_u *p; - - line = get_cursor_line_ptr(); - p = line + curwin->w_cursor.col; + char_u *line = get_cursor_line_ptr(); + char_u *p = line + curwin->w_cursor.col; MB_PTR_BACK(line, p); + ptrdiff_t p_off = p - line; // Stop completion when the whole word was deleted. For Omni completion // allow the word to be deleted, we won't match everything. @@ -3369,8 +3367,12 @@ static int ins_compl_bs(void) ins_compl_restart(); } + // ins_compl_restart() calls update_screen(0) which may invalidate the pointer + // TODO(bfredl): get rid of random update_screen() calls deep inside completion logic + line = get_cursor_line_ptr(); + xfree(compl_leader); - compl_leader = vim_strnsave(line + compl_col, (int)(p - line) - compl_col); + compl_leader = vim_strnsave(line + compl_col, (int)p_off - compl_col); ins_compl_new_leader(); if (compl_shown_match != NULL) { // Make sure current match is not a hidden item. diff --git a/src/nvim/eval.c b/src/nvim/eval.c index ae64732eb9..768b82b464 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5848,8 +5848,8 @@ static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate) { char_u *name; char_u *string = NULL; - int len; - int cc; + int len; + int cc; ++*arg; name = *arg; @@ -6193,7 +6193,7 @@ int assert_inrange(typval_T *argvars) char msg[55]; vim_snprintf(msg, sizeof(msg), "range %" PRIdVARNUMBER " - %" PRIdVARNUMBER ",", - lower, upper); + lower, upper); // -V576 fill_assert_error(&ga, &argvars[3], (char_u *)msg, NULL, &argvars[2], ASSERT_INRANGE); assert_error(&ga); @@ -6299,9 +6299,9 @@ int assert_fails(typval_T *argvars) FUNC_ATTR_NONNULL_ALL { const char *const cmd = tv_get_string_chk(&argvars[0]); - garray_T ga; + garray_T ga; int ret = 0; - int save_trylevel = trylevel; + int save_trylevel = trylevel; // trylevel must be zero for a ":throw" command to be considered failed trylevel = 0; @@ -7345,7 +7345,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T const char *line = NULL; list_T *l = NULL; listitem_T *li = NULL; - long added = 0; + long added = 0; linenr_T append_lnum; buf_T *curbuf_save = NULL; win_T *curwin_save = NULL; @@ -8807,9 +8807,9 @@ char_u *set_cmdarg(exarg_T *eap, char_u *oldarg) char_u *newval = xmalloc(newval_len); if (eap->force_bin == FORCE_BIN) { - sprintf((char *)newval, " ++bin"); + snprintf((char *)newval, newval_len, " ++bin"); } else if (eap->force_bin == FORCE_NOBIN) { - sprintf((char *)newval, " ++nobin"); + snprintf((char *)newval, newval_len, " ++nobin"); } else { *newval = NUL; } diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index c0a18b3236..762d741fb7 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -166,6 +166,7 @@ return { getpos={args=1}, getqflist={args={0, 1}}, getreg={args={0, 3}}, + getreginfo={args={0, 1}, base=1}, getregtype={args={0, 1}}, gettabinfo={args={0, 1}}, gettabvar={args={2, 3}}, diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index e7fb6ed504..9feecadb6f 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -248,7 +248,7 @@ static int non_zero_arg(typval_T *argvars) static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T f; - float_T (*function)(float_T) = (float_T (*)(float_T))fptr; + float_T (*function)(float_T) = (float_T (*)(float_T)) fptr; rettv->v_type = VAR_FLOAT; if (tv_get_float_chk(argvars, &f)) { @@ -1802,7 +1802,7 @@ static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_number = diff_check_fill(curwin, tv_get_lnum(argvars)); + rettv->vval.v_number = MAX(0, diff_check(curwin, tv_get_lnum(argvars))); } /* @@ -2695,13 +2695,13 @@ static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - linenr_T foldstart; - linenr_T foldend; + linenr_T foldstart; + linenr_T foldend; char_u *dashes; - linenr_T lnum; + linenr_T lnum; char_u *s; char_u *r; - int len; + int len; char *txt; rettv->v_type = VAR_STRING; @@ -3310,10 +3310,10 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *pat; - expand_T xpc; - bool filtered = false; - int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH - | WILD_NO_BEEP; + expand_T xpc; + bool filtered = false; + int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH + | WILD_NO_BEEP; if (argvars[1].v_type != VAR_STRING) { EMSG2(_(e_invarg2), "type must be a string"); @@ -4113,8 +4113,8 @@ static void f_win_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) // static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags) { - int dir; - int height = wp->w_height; + int dir; + int height = wp->w_height; win_T *oldwin = curwin; if (wp == targetwin) { @@ -4153,7 +4153,7 @@ static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *wp; win_T *targetwin; - int flags = 0, size = 0; + int flags = 0, size = 0; wp = find_win_by_nr_or_id(&argvars[0]); targetwin = find_win_by_nr_or_id(&argvars[1]); @@ -5968,7 +5968,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, const SomeMatchType type) { char_u *str = NULL; - long len = 0; + long len = 0; char_u *expr = NULL; regmatch_T regmatch; char_u *save_cpo; @@ -7218,6 +7218,61 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) fclose(fd); } +/// "getreginfo()" function +static void f_getreginfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + const char *strregname; + if (argvars[0].v_type != VAR_UNKNOWN) { + strregname = tv_get_string_chk(&argvars[0]); + if (strregname == NULL) { + return; + } + } else { + strregname = (const char *)get_vim_var_str(VV_REG); + } + + int regname = (strregname == NULL ? '"' : *strregname); + if (regname == 0 || regname == '@') { + regname = '"'; + } + + tv_dict_alloc_ret(rettv); + dict_T *const dict = rettv->vval.v_dict; + + list_T *const list = get_reg_contents(regname, kGRegExprSrc | kGRegList); + if (list == NULL) { + return; + } + tv_dict_add_list(dict, S_LEN("regcontents"), list); + + char buf[NUMBUFLEN + 2]; + buf[0] = NUL; + buf[1] = NUL; + colnr_T reglen = 0; + switch (get_reg_type(regname, ®len)) { + case kMTLineWise: + buf[0] = 'V'; + break; + case kMTCharWise: + buf[0] = 'v'; + break; + case kMTBlockWise: + vim_snprintf(buf, sizeof(buf), "%c%d", Ctrl_V, reglen + 1); + break; + case kMTUnknown: + abort(); + } + tv_dict_add_str(dict, S_LEN("regtype"), buf); + + buf[0] = get_register_name(get_unname_register()); + buf[1] = NUL; + if (regname == '"') { + tv_dict_add_str(dict, S_LEN("points_to"), buf); + } else { + tv_dict_add_bool(dict, S_LEN("isunnamed"), regname == buf[0] ? kBoolVarTrue : kBoolVarFalse); + } +} + // "reg_executing()" function static void f_reg_executing(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -9001,7 +9056,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T pos; int fnum; - colnr_T curswant = -1; + colnr_T curswant = -1; rettv->vval.v_number = -1; const char *const name = tv_get_string_chk(argvars); @@ -9039,6 +9094,36 @@ static void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) set_qf_ll_list(NULL, argvars, rettv); } +/// Translate a register type string to the yank type and block length +static int get_yank_type(char_u **const pp, MotionType *const yank_type, long *const block_len) + FUNC_ATTR_NONNULL_ALL +{ + char_u *stropt = *pp; + switch (*stropt) { + case 'v': + case 'c': // character-wise selection + *yank_type = kMTCharWise; + break; + case 'V': + case 'l': // line-wise selection + *yank_type = kMTLineWise; + break; + case 'b': + case Ctrl_V: // block-wise selection + *yank_type = kMTBlockWise; + if (ascii_isdigit(stropt[1])) { + stropt++; + *block_len = getdigits_long(&stropt, false, 0) - 1; + stropt--; + } + break; + default: + return FAIL; + } + *pp = stropt; + return OK; +} + /* * "setreg()" function */ @@ -9063,8 +9148,53 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) regname = '"'; } + const typval_T *regcontents = NULL; + int pointreg = 0; + if (argvars[1].v_type == VAR_DICT) { + dict_T *const d = argvars[1].vval.v_dict; + + if (tv_dict_len(d) == 0) { + // Empty dict, clear the register (like setreg(0, [])) + char_u *lstval[2] = { NULL, NULL }; + write_reg_contents_lst(regname, lstval, false, kMTUnknown, -1); + return; + } + + dictitem_T *const di = tv_dict_find(d, "regcontents", -1); + if (di != NULL) { + regcontents = &di->di_tv; + } + + const char *stropt = tv_dict_get_string(d, "regtype", false); + if (stropt != NULL) { + const int ret = get_yank_type((char_u **)&stropt, &yank_type, &block_len); + + if (ret == FAIL || *(++stropt) != NUL) { + EMSG2(_(e_invargval), "value"); + return; + } + } + + if (regname == '"') { + stropt = tv_dict_get_string(d, "points_to", false); + if (stropt != NULL) { + pointreg = *stropt; + regname = pointreg; + } + } else if (tv_dict_get_number(d, "isunnamed")) { + pointreg = regname; + } + } else { + regcontents = &argvars[1]; + } + bool set_unnamed = false; if (argvars[2].v_type != VAR_UNKNOWN) { + if (yank_type != kMTUnknown) { + EMSG2(_(e_toomanyarg), "setreg"); + return; + } + const char *stropt = tv_get_string_chk(&argvars[2]); if (stropt == NULL) { return; // Type error. @@ -9075,33 +9205,18 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) case 'A': // append append = true; break; - case 'v': - case 'c': // character-wise selection - yank_type = kMTCharWise; - break; - case 'V': - case 'l': // line-wise selection - yank_type = kMTLineWise; - break; - case 'b': - case Ctrl_V: // block-wise selection - yank_type = kMTBlockWise; - if (ascii_isdigit(stropt[1])) { - stropt++; - block_len = getdigits_long((char_u **)&stropt, true, 0) - 1; - stropt--; - } - break; case 'u': case '"': // unnamed register set_unnamed = true; break; + default: + get_yank_type((char_u **)&stropt, &yank_type, &block_len); } } } - if (argvars[1].v_type == VAR_LIST) { - list_T *ll = argvars[1].vval.v_list; + if (regcontents != NULL && regcontents->v_type == VAR_LIST) { + list_T *const ll = regcontents->vval.v_list; // If the list is NULL handle like an empty list. const int len = tv_list_len(ll); @@ -9137,14 +9252,17 @@ free_lstval: xfree(*--curallocval); } xfree(lstval); - } else { - const char *strval = tv_get_string_chk(&argvars[1]); + } else if (regcontents != NULL) { + const char *const strval = tv_get_string_chk(regcontents); if (strval == NULL) { return; } write_reg_contents_ex(regname, (const char_u *)strval, STRLEN(strval), append, yank_type, block_len); } + if (pointreg != 0) { + get_yank_register(pointreg, YREG_YANK); + } rettv->vval.v_number = 0; if (set_unnamed) { @@ -9201,7 +9319,7 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) static char *e_invact2 = N_("E962: Invalid action: '%s'"); win_T *wp; dict_T *d; - int action = 'r'; + int action = 'r'; rettv->vval.v_number = -1; @@ -10683,7 +10801,7 @@ static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)transstr(tv_get_string(&argvars[0])); + rettv->vval.v_string = (char_u *)transstr(tv_get_string(&argvars[0]), true); } /* diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 77297f9ffa..0e4ddffa33 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -68,11 +68,11 @@ void func_init(void) static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, int *varargs, garray_T *default_args, bool skip) { - bool mustend = false; + bool mustend = false; char_u *arg = *argp; char_u *p = arg; - int c; - int i; + int c; + int i; if (newargs != NULL) { ga_init(newargs, (int)sizeof(char_u *), 3); @@ -205,8 +205,8 @@ static void register_closure(ufunc_T *fp) /// Get a name for a lambda. Returned in static memory. char_u *get_lambda_name(void) { - static char_u name[30]; - static int lambda_no = 0; + static char_u name[30]; + static int lambda_no = 0; snprintf((char *)name, sizeof(name), "<lambda>%d", ++lambda_no); return name; @@ -217,16 +217,16 @@ char_u *get_lambda_name(void) /// @return OK or FAIL. Returns NOTDONE for dict or {expr}. int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate) { - garray_T newargs = GA_EMPTY_INIT_VALUE; + garray_T newargs = GA_EMPTY_INIT_VALUE; garray_T *pnewargs; ufunc_T *fp = NULL; partial_T *pt = NULL; - int varargs; - int ret; + int varargs; + int ret; char_u *start = skipwhite(*arg + 1); char_u *s, *e; bool *old_eval_lavars = eval_lavars_used; - bool eval_lavars = false; + bool eval_lavars = false; // First, check if this is a lambda expression. "->" must exists. ret = get_function_args(&start, '-', NULL, NULL, NULL, true); diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index f8186c000e..bbc1dd9717 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1800,7 +1800,7 @@ int do_write(exarg_T *eap) int retval = FAIL; char_u *free_fname = NULL; buf_T *alt_buf = NULL; - int name_was_missing; + int name_was_missing; if (not_writing()) { // check 'write' option return FAIL; @@ -2294,8 +2294,8 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new char_u *new_name = NULL; bool did_set_swapcommand = false; buf_T *buf; - bufref_T bufref; - bufref_T old_curbuf; + bufref_T bufref; + bufref_T old_curbuf; char_u *free_fname = NULL; int retval = FAIL; long n; @@ -3078,7 +3078,7 @@ void ex_change(exarg_T *eap) void ex_z(exarg_T *eap) { char_u *x; - int64_t bigness; + int64_t bigness; char_u *kind; int minus = 0; linenr_T start, end, curs, i; @@ -5549,8 +5549,9 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname, if (add_help_tags || path_full_compare((char_u *)"$VIMRUNTIME/doc", dir, false, true) == kEqualFiles) { - s = xmalloc(18 + STRLEN(tagfname)); - sprintf((char *)s, "help-tags\t%s\t1\n", tagfname); + size_t s_len = 18 + STRLEN(tagfname); + s = xmalloc(s_len); + snprintf((char *)s, s_len, "help-tags\t%s\t1\n", tagfname); GA_APPEND(char_u *, &ga, s); } @@ -5611,10 +5612,11 @@ static void helptags_one(char_u *dir, const char_u *ext, const char_u *tagfname, && (vim_strchr((char_u *)" \t\n\r", s[1]) != NULL || s[1] == '\0')) { *p2 = '\0'; - ++p1; - s = xmalloc((p2 - p1) + STRLEN(fname) + 2); + p1++; + size_t s_len= (p2 - p1) + STRLEN(fname) + 2; + s = xmalloc(s_len); GA_APPEND(char_u *, &ga, s); - sprintf((char *)s, "%s\t%s", p1, fname); + snprintf((char *)s, s_len, "%s\t%s", p1, fname); // find next '*' p2 = vim_strchr(p2 + 1, '*'); diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index d8827f0a3d..7f3b019d57 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -317,7 +317,7 @@ static void profile_reset(void) } // Reset functions. - size_t n = func_hashtab.ht_used; + size_t n = func_hashtab.ht_used; hashitem_T *hi = func_hashtab.ht_array; for (; n > (size_t)0; hi++) { @@ -1703,8 +1703,8 @@ void init_pyxversion(void) static int requires_py_version(char_u *filename) { FILE *file; - int requires_py_version = 0; - int i, lines; + int requires_py_version = 0; + int i, lines; lines = (int)p_mls; if (lines < 0) { @@ -1950,7 +1950,7 @@ static int source_using_linegetter(void *cookie, LineGetter fgetline, const char snprintf((char *)sourcing_name_buf, sizeof(sourcing_name_buf), "%s called at %s:%" PRIdLINENR, traceback_name, save_sourcing_name, save_sourcing_lnum); - sourcing_name = sourcing_name_buf; + sourcing_name = sourcing_name_buf; // -V507 reassigned below, before return. } sourcing_lnum = 0; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 68dd039278..70057ffd46 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5637,7 +5637,7 @@ static void ex_command(exarg_T *eap) uint32_t argt = 0; long def = -1; int flags = 0; - int compl = EXPAND_NOTHING; + int compl = EXPAND_NOTHING; char_u *compl_arg = NULL; cmd_addr_T addr_type_arg = ADDR_NONE; int has_attr = (eap->arg[0] == '-'); diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index ddf60eac18..5f0dca736a 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -140,25 +140,25 @@ static unsigned last_prompt_id = 0; // Struct to store the viewstate during 'incsearch' highlighting. typedef struct { - colnr_T vs_curswant; - colnr_T vs_leftcol; - linenr_T vs_topline; - int vs_topfill; - linenr_T vs_botline; - int vs_empty_rows; + colnr_T vs_curswant; + colnr_T vs_leftcol; + linenr_T vs_topline; + int vs_topfill; + linenr_T vs_botline; + int vs_empty_rows; } viewstate_T; // Struct to store the state of 'incsearch' highlighting. typedef struct { - pos_T search_start; // where 'incsearch' starts searching - pos_T save_cursor; + pos_T search_start; // where 'incsearch' starts searching + pos_T save_cursor; viewstate_T init_viewstate; viewstate_T old_viewstate; - pos_T match_start; - pos_T match_end; - bool did_incsearch; - bool incsearch_postponed; - int magic_save; + pos_T match_start; + pos_T match_end; + bool did_incsearch; + bool incsearch_postponed; + int magic_save; } incsearch_state_T; typedef struct command_line_state { @@ -178,8 +178,8 @@ typedef struct command_line_state { int did_wild_list; // did wild_list() recently int wim_index; // index in wim_flags[] int res; - int save_msg_scroll; - int save_State; // remember State when called + int save_msg_scroll; + int save_State; // remember State when called char_u *save_p_icm; int some_key_typed; // one of the keys was typed // mouse drag and release events are ignored, unless they are @@ -383,7 +383,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s // Don't do 'hlsearch' highlighting if the pattern matches everything. if (!use_last_pat) { char_u c = *end; - int empty; + int empty; *end = NUL; empty = empty_pattern(p); @@ -1502,7 +1502,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_ ui_busy_start(); ui_flush(); - pos_T t; + pos_T t; char_u *pat; int search_flags = SEARCH_NOOF; char_u save; @@ -5272,7 +5272,7 @@ static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file) { char_u *e; - garray_T ga; + garray_T ga; char_u *const retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp, num_file, file); @@ -6250,8 +6250,8 @@ int hist_type2char(int type) static int open_cmdwin(void) { struct cmdline_info save_ccline; - bufref_T old_curbuf; - bufref_T bufref; + bufref_T old_curbuf; + bufref_T bufref; win_T *old_curwin = curwin; win_T *wp; int i; diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 11e8353e3a..4aadd77d45 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -450,11 +450,11 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr } } else if (fprintf(fd, "let s:l = %" PRIdLINENR " - ((%" PRIdLINENR - " * winheight(0) + %" PRId64 ") / %" PRId64 ")\n", + " * winheight(0) + %d) / %d)\n", wp->w_cursor.lnum, wp->w_cursor.lnum - wp->w_topline, - (int64_t)(wp->w_height_inner / 2), - (int64_t)wp->w_height_inner) < 0) { + (wp->w_height_inner / 2), + wp->w_height_inner) < 0) { return FAIL; } if (fprintf(fd, diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index 819b8ad3dc..cf01c305d7 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -56,8 +56,8 @@ static ExtmarkNs *buf_ns_ref(buf_T *buf, uint64_t ns_id, bool put) { /// Create or update an extmark /// /// must not be used during iteration! -/// @returns the mark id -uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id, int row, colnr_T col, int end_row, +/// @returns the internal mark id +uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t *idp, int row, colnr_T col, int end_row, colnr_T end_col, Decoration *decor, bool right_gravity, bool end_right_gravity, ExtmarkOp op) { @@ -65,6 +65,7 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id, int row, colnr_T c assert(ns != NULL); mtpos_t old_pos; uint64_t mark = 0; + uint64_t id = idp ? *idp : 0; if (id == 0) { id = ns->free_id++; @@ -118,7 +119,11 @@ revised: if (decor) { decor_redraw(buf, row, end_row > -1 ? end_row : row, decor); } - return id; + + if (idp) { + *idp = id; + } + return mark; } static bool extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col) @@ -169,6 +174,10 @@ bool extmark_del(buf_T *buf, uint64_t ns_id, uint64_t id) decor_free(item.decor); } + if (mark == buf->b_virt_line_mark) { + clear_virt_lines(buf, pos.row); + } + map_del(uint64_t, uint64_t)(ns->map, id); map_del(uint64_t, ExtmarkItem)(buf->b_extmark_index, mark); @@ -227,6 +236,9 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id, int l_row, colnr_T l_col, int u_r } uint64_t start_id = mark.id & ~MARKTREE_END_FLAG; + if (start_id == buf->b_virt_line_mark) { + clear_virt_lines(buf, mark.row); + } ExtmarkItem item = map_get(uint64_t, ExtmarkItem)(buf->b_extmark_index, start_id); @@ -496,6 +508,7 @@ void extmark_apply_undo(ExtmarkUndoObject undo_info, bool undo) kExtmarkNoUndo); } } + curbuf->b_virt_line_pos = -1; } @@ -574,7 +587,8 @@ void extmark_splice_impl(buf_T *buf, int start_row, colnr_T start_col, bcount_t int old_row, colnr_T old_col, bcount_t old_byte, int new_row, colnr_T new_col, bcount_t new_byte, ExtmarkOp undo) { - curbuf->deleted_bytes2 = 0; + buf->deleted_bytes2 = 0; + buf->b_virt_line_pos = -1; buf_updates_send_splice(buf, start_row, start_col, start_byte, old_row, old_col, old_byte, new_row, new_col, new_byte); @@ -665,7 +679,8 @@ void extmark_move_region(buf_T *buf, int start_row, colnr_T start_col, bcount_t int extent_row, colnr_T extent_col, bcount_t extent_byte, int new_row, colnr_T new_col, bcount_t new_byte, ExtmarkOp undo) { - curbuf->deleted_bytes2 = 0; + buf->deleted_bytes2 = 0; + buf->b_virt_line_pos = -1; // TODO(bfredl): this is not synced to the buffer state inside the callback. // But unless we make the undo implementation smarter, this is not ensured // anyway. diff --git a/src/nvim/extmark_defs.h b/src/nvim/extmark_defs.h index b5d91382ec..2da4f3dc00 100644 --- a/src/nvim/extmark_defs.h +++ b/src/nvim/extmark_defs.h @@ -6,6 +6,16 @@ typedef struct Decoration Decoration; +typedef struct { + char *text; + int hl_id; +} VirtTextChunk; + +typedef kvec_t(VirtTextChunk) VirtText; +#define VIRTTEXT_EMPTY ((VirtText)KV_INITIAL_VALUE) +typedef kvec_t(VirtText) VirtLines; + + typedef struct { uint64_t ns_id; diff --git a/src/nvim/fold.c b/src/nvim/fold.c index 7a017702ee..f22fa449ea 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -1875,7 +1875,7 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldin } } if (*p != NUL) { - p = (char_u *)transstr((const char *)text); + p = (char_u *)transstr((const char *)text, true); xfree(text); text = p; } diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c index b89807b9f1..2a1f39083c 100644 --- a/src/nvim/lua/xdiff.c +++ b/src/nvim/lua/xdiff.c @@ -265,8 +265,8 @@ int nlua_xdl_diff(lua_State *lstate) Error err = ERROR_INIT; xdemitconf_t cfg; - xpparam_t params; - xdemitcb_t ecb; + xpparam_t params; + xdemitcb_t ecb; memset(&cfg, 0, sizeof(cfg)); memset(¶ms, 0, sizeof(params)); diff --git a/src/nvim/memory.c b/src/nvim/memory.c index cc9c047fa0..0f5f4c1e40 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -170,6 +170,8 @@ void *xrealloc(void *ptr, size_t size) /// xmalloc() wrapper that allocates size + 1 bytes and zeroes the last byte /// +/// Commonly used to allocate strings, e.g. `char *s = xmallocz(len)`. +/// /// @see {xmalloc} /// @param size /// @return pointer to allocated space. Never NULL diff --git a/src/nvim/message.c b/src/nvim/message.c index f9fe7774f6..ed673b52d3 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -762,7 +762,7 @@ bool emsgf_multiline(const char *const fmt, ...) va_list ap; - static char errbuf[MULTILINE_BUFSIZE]; + static char errbuf[MULTILINE_BUFSIZE]; if (emsg_not_now()) { return true; } diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index b65d87e617..cf463fd40a 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -241,7 +241,7 @@ retnomove: if (row < 0) { count = 0; for (first = true; curwin->w_topline > 1; ) { - if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) { + if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)) { count++; } else { count += plines_win(curwin, curwin->w_topline - 1, true); @@ -251,8 +251,8 @@ retnomove: } first = false; (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); - if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) { - ++curwin->w_topfill; + if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)) { + curwin->w_topfill++; } else { --curwin->w_topline; curwin->w_topfill = 0; @@ -283,11 +283,10 @@ retnomove: } if (curwin->w_topfill > 0) { - --curwin->w_topfill; + curwin->w_topfill--; } else { - ++curwin->w_topline; - curwin->w_topfill = - diff_check_fill(curwin, curwin->w_topline); + curwin->w_topline++; + curwin->w_topfill = win_get_fill(curwin, curwin->w_topline); } } check_topfill(curwin, false); @@ -373,12 +372,12 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump) while (row > 0) { // Don't include filler lines in "count" - if (win->w_p_diff + if (win_may_fill(win) && !hasFoldingWin(win, lnum, NULL, NULL, true, NULL)) { if (lnum == win->w_topline) { row -= win->w_topfill; } else { - row -= diff_check_fill(win, lnum); + row -= win_get_fill(win, lnum); } count = plines_win_nofill(win, lnum, true); } else { diff --git a/src/nvim/move.c b/src/nvim/move.c index 3a5b2fb211..ca3dd34204 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -197,7 +197,7 @@ void update_topline(win_T *wp) } } // Check if there are more filler lines than allowed. - if (!check_topline && wp->w_topfill > diff_check_fill(wp, wp->w_topline)) { + if (!check_topline && wp->w_topfill > win_get_fill(wp, wp->w_topline)) { check_topline = true; } @@ -582,8 +582,7 @@ static void curs_rows(win_T *wp) --i; // hold at inserted lines } } - if (valid - && (lnum != wp->w_topline || !wp->w_p_diff)) { + if (valid && (lnum != wp->w_topline || !win_may_fill(wp))) { lnum = wp->w_lines[i].wl_lastlnum + 1; // Cursor inside folded lines, don't count this row if (lnum > wp->w_cursor.lnum) { @@ -854,7 +853,7 @@ void curs_columns(win_T *wp, int may_scroll) if (wp->w_cursor.lnum == wp->w_topline) { wp->w_wrow += wp->w_topfill; } else { - wp->w_wrow += diff_check_fill(wp, wp->w_cursor.lnum); + wp->w_wrow += win_get_fill(wp, wp->w_cursor.lnum); } prev_skipcol = wp->w_skipcol; @@ -992,7 +991,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp, if ((local && existing_row) || visible_row) { colnr_T off; colnr_T col; - int width; + int width; getvcol(wp, pos, &scol, &ccol, &ecol); @@ -1041,7 +1040,7 @@ bool scrolldown(long line_count, int byfold) (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); validate_cursor(); // w_wrow needs to be valid while (line_count-- > 0) { - if (curwin->w_topfill < diff_check(curwin, curwin->w_topline) + if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline) && curwin->w_topfill < curwin->w_height_inner - 1) { curwin->w_topfill++; done++; @@ -1122,7 +1121,7 @@ bool scrollup(long line_count, int byfold) linenr_T botline = curwin->w_botline; if ((byfold && hasAnyFolding(curwin)) - || curwin->w_p_diff) { + || win_may_fill(curwin)) { // count each sequence of folded lines as one logical line linenr_T lnum = curwin->w_topline; while (line_count--) { @@ -1135,8 +1134,8 @@ bool scrollup(long line_count, int byfold) if (lnum >= curbuf->b_ml.ml_line_count) { break; } - ++lnum; - curwin->w_topfill = diff_check_fill(curwin, lnum); + lnum++; + curwin->w_topfill = win_get_fill(curwin, lnum); } } // approximate w_botline @@ -1207,7 +1206,7 @@ static void max_topfill(void) if (n >= curwin->w_height_inner) { curwin->w_topfill = 0; } else { - curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline); + curwin->w_topfill = win_get_fill(curwin, curwin->w_topline); if (curwin->w_topfill + n > curwin->w_height_inner) { curwin->w_topfill = curwin->w_height_inner - n; } @@ -1220,8 +1219,7 @@ static void max_topfill(void) */ void scrolldown_clamp(void) { - int can_fill = (curwin->w_topfill - < diff_check_fill(curwin, curwin->w_topline)); + int can_fill = (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)); if (curwin->w_topline <= 1 && !can_fill) { @@ -1302,7 +1300,7 @@ void scrollup_clamp(void) */ static void topline_back(win_T *wp, lineoff_T *lp) { - if (lp->fill < diff_check_fill(wp, lp->lnum)) { + if (lp->fill < win_get_fill(wp, lp->lnum)) { // Add a filler line lp->fill++; lp->height = 1; @@ -1328,7 +1326,7 @@ static void topline_back(win_T *wp, lineoff_T *lp) */ static void botline_forw(win_T *wp, lineoff_T *lp) { - if (lp->fill < diff_check_fill(wp, lp->lnum + 1)) { + if (lp->fill < win_get_fill(wp, lp->lnum + 1)) { // Add a filler line. lp->fill++; lp->height = 1; @@ -1355,8 +1353,8 @@ static void botline_forw(win_T *wp, lineoff_T *lp) static void botline_topline(lineoff_T *lp) { if (lp->fill > 0) { - ++lp->lnum; - lp->fill = diff_check_fill(curwin, lp->lnum) - lp->fill + 1; + lp->lnum++; + lp->fill = win_get_fill(curwin, lp->lnum) - lp->fill + 1; } } @@ -1368,8 +1366,8 @@ static void botline_topline(lineoff_T *lp) static void topline_botline(lineoff_T *lp) { if (lp->fill > 0) { - lp->fill = diff_check_fill(curwin, lp->lnum) - lp->fill + 1; - --lp->lnum; + lp->fill = win_get_fill(curwin, lp->lnum) - lp->fill + 1; + lp->lnum--; } } @@ -1417,7 +1415,7 @@ void scroll_cursor_top(int min_scroll, int always) // "used" already contains the number of filler lines above, don't add it // again. // Hide filler lines above cursor line by adding them to "extra". - int extra = diff_check_fill(curwin, curwin->w_cursor.lnum); + 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, @@ -1475,7 +1473,7 @@ void scroll_cursor_top(int min_scroll, int always) if (curwin->w_topline > curwin->w_cursor.lnum) { curwin->w_topline = curwin->w_cursor.lnum; } - curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline); + curwin->w_topfill = win_get_fill(curwin, curwin->w_topline); if (curwin->w_topfill > 0 && extra > off) { curwin->w_topfill -= extra - off; if (curwin->w_topfill < 0) { @@ -1505,7 +1503,7 @@ void set_empty_rows(win_T *wp, int used) } else { wp->w_empty_rows = wp->w_height_inner - used; if (wp->w_botline <= wp->w_buffer->b_ml.ml_line_count) { - wp->w_filler_rows = diff_check_fill(wp, wp->w_botline); + wp->w_filler_rows = win_get_fill(wp, wp->w_botline); if (wp->w_empty_rows > wp->w_filler_rows) { wp->w_empty_rows -= wp->w_filler_rows; } else { @@ -1531,10 +1529,10 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) lineoff_T boff; int fill_below_window; linenr_T old_topline = curwin->w_topline; - int old_topfill = curwin->w_topfill; + int old_topfill = curwin->w_topfill; linenr_T old_botline = curwin->w_botline; - int old_valid = curwin->w_valid; - int old_empty_rows = curwin->w_empty_rows; + int old_valid = curwin->w_valid; + int old_empty_rows = curwin->w_empty_rows; linenr_T cln = curwin->w_cursor.lnum; // Cursor Line Number long so = get_scrolloff_value(curwin); @@ -1590,7 +1588,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) } loff.fill = 0; boff.fill = 0; - fill_below_window = diff_check_fill(curwin, curwin->w_botline) + fill_below_window = win_get_fill(curwin, curwin->w_botline) - curwin->w_filler_rows; while (loff.lnum > 1) { @@ -1835,7 +1833,7 @@ void cursor_correct(void) // Count filler lines below this line as context. if (topline < botline) { - above += diff_check_fill(curwin, topline + 1); + above += win_get_fill(curwin, topline + 1); } ++topline; } @@ -1889,9 +1887,7 @@ int onepage(Direction dir, long count) ? ((curwin->w_topline >= curbuf->b_ml.ml_line_count - so) && curwin->w_botline > curbuf->b_ml.ml_line_count) : (curwin->w_topline == 1 - && curwin->w_topfill == - diff_check_fill(curwin, curwin->w_topline) - )) { + && curwin->w_topfill == win_get_fill(curwin, curwin->w_topline))) { beep_flush(); retval = FAIL; break; @@ -1919,7 +1915,7 @@ int onepage(Direction dir, long count) /* For the overlap, start with the line just below the window * and go upwards. */ loff.lnum = curwin->w_botline; - loff.fill = diff_check_fill(curwin, loff.lnum) + loff.fill = win_get_fill(curwin, loff.lnum) - curwin->w_filler_rows; get_scroll_overlap(&loff, -1); curwin->w_topline = loff.lnum; @@ -1956,8 +1952,7 @@ int onepage(Direction dir, long count) * line at the bottom of the window. Make sure this results in * the same line as before doing CTRL-F. */ loff.lnum = curwin->w_topline - 1; - loff.fill = diff_check_fill(curwin, loff.lnum + 1) - - curwin->w_topfill; + loff.fill = win_get_fill(curwin, loff.lnum + 1) - curwin->w_topfill; get_scroll_overlap(&loff, 1); if (loff.lnum >= curbuf->b_ml.ml_line_count) { @@ -2000,8 +1995,7 @@ int onepage(Direction dir, long count) /* First try using the maximum number of filler lines. If * that's not enough, backup one line. */ loff.fill = curwin->w_topfill; - if (curwin->w_topfill < diff_check_fill(curwin, - curwin->w_topline)) { + if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)) { max_topfill(); } if (curwin->w_topfill == loff.fill) { @@ -2146,8 +2140,8 @@ void halfpage(bool flag, linenr_T Prenum) break; } (void)hasFolding(curwin->w_topline, NULL, &curwin->w_topline); - ++curwin->w_topline; - curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline); + curwin->w_topline++; + 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; @@ -2158,11 +2152,9 @@ void halfpage(bool flag, linenr_T Prenum) curwin->w_valid &= ~(VALID_CROW|VALID_WROW); scrolled += i; - /* - * Correct w_botline for changed w_topline. - * Won't work when there are filler lines. - */ - if (curwin->w_p_diff) { + // Correct w_botline for changed w_topline. + // Won't work when there are filler lines. + if (win_may_fill(curwin)) { curwin->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP); } else { room += i; @@ -2197,7 +2189,7 @@ void halfpage(bool flag, linenr_T Prenum) * scroll the text down */ while (n > 0 && curwin->w_topline > 1) { - if (curwin->w_topfill < diff_check_fill(curwin, curwin->w_topline)) { + if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)) { i = 1; n--; curwin->w_topfill++; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index b8a62a8fea..17ec5cd3be 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -5261,16 +5261,15 @@ static void nv_scroll(cmdarg_T *cap) } else { if (cap->cmdchar == 'M') { // Don't count filler lines above the window. - used -= diff_check_fill(curwin, curwin->w_topline) + used -= win_get_fill(curwin, curwin->w_topline) - curwin->w_topfill; validate_botline(curwin); // make sure w_empty_rows is valid half = (curwin->w_height_inner - curwin->w_empty_rows + 1) / 2; for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; n++) { // Count half he number of filler lines to be "below this // line" and half to be "above the next line". - if (n > 0 && used + diff_check_fill(curwin, curwin->w_topline - + n) / 2 >= half) { - --n; + if (n > 0 && used + win_get_fill(curwin, curwin->w_topline + n) / 2 >= half) { + n--; break; } used += plines_win(curwin, curwin->w_topline + n, true); diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 12fb8439f1..1d737ee9fc 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -804,12 +804,6 @@ bool valid_yank_reg(int regname, bool writing) return false; } -typedef enum { - YREG_PASTE, - YREG_YANK, - YREG_PUT, -} yreg_mode_t; - /// 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! @@ -3650,6 +3644,12 @@ 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]); +} + /* * ":dis" and ":registers": Display the contents of the yank registers. */ @@ -5560,6 +5560,11 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char_u *str } } + // Without any lines make the register empty. + if (y_ptr->y_size + newlines == 0) { + XFREE_CLEAR(y_ptr->y_array); + return; + } // Grow the register array to hold the pointers to the new lines. char_u **pp = xrealloc(y_ptr->y_array, diff --git a/src/nvim/ops.h b/src/nvim/ops.h index 112ffbeaba..5b87746921 100644 --- a/src/nvim/ops.h +++ b/src/nvim/ops.h @@ -90,6 +90,13 @@ typedef struct yankreg { dict_T *additional_data; ///< Additional data from ShaDa file. } yankreg_T; +/// Modes for get_yank_register() +typedef enum { + YREG_PASTE, + YREG_YANK, + YREG_PUT, +} yreg_mode_t; + /// Convert register name into register index /// /// @param[in] regname Register name. diff --git a/src/nvim/option.c b/src/nvim/option.c index 4073ab08d9..77a161a3e1 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -22,50 +22,50 @@ #define IN_OPTION_C #include <assert.h> #include <inttypes.h> +#include <limits.h> #include <stdbool.h> -#include <string.h> #include <stdlib.h> -#include <limits.h> +#include <string.h> -#include "nvim/vim.h" -#include "nvim/macros.h" #include "nvim/ascii.h" -#include "nvim/edit.h" -#include "nvim/option.h" #include "nvim/buffer.h" #include "nvim/charset.h" #include "nvim/cursor.h" +#include "nvim/cursor_shape.h" #include "nvim/diff.h" #include "nvim/digraph.h" +#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" #include "nvim/fileio.h" #include "nvim/fold.h" +#include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/hardcopy.h" #include "nvim/highlight.h" #include "nvim/indent_c.h" +#include "nvim/keymap.h" +#include "nvim/macros.h" #include "nvim/mbyte.h" #include "nvim/memfile.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/misc1.h" -#include "nvim/runtime.h" -#include "nvim/keymap.h" -#include "nvim/garray.h" -#include "nvim/cursor_shape.h" -#include "nvim/move.h" #include "nvim/mouse.h" +#include "nvim/move.h" #include "nvim/normal.h" +#include "nvim/option.h" +#include "nvim/os/os.h" #include "nvim/os_unix.h" #include "nvim/path.h" #include "nvim/popupmnu.h" #include "nvim/regexp.h" -#include "nvim/ex_session.h" +#include "nvim/runtime.h" #include "nvim/screen.h" #include "nvim/spell.h" #include "nvim/spellfile.h" @@ -74,13 +74,13 @@ #include "nvim/ui.h" #include "nvim/ui_compositor.h" #include "nvim/undo.h" +#include "nvim/vim.h" #include "nvim/window.h" -#include "nvim/os/os.h" #ifdef WIN32 # include "nvim/os/pty_conpty_win.h" #endif -#include "nvim/lua/executor.h" #include "nvim/api/private/helpers.h" +#include "nvim/lua/executor.h" #include "nvim/os/input.h" #include "nvim/os/lang.h" #include "nvim/quickfix.h" @@ -124,64 +124,64 @@ static char *p_ttytype = NULL; static int p_ai; static int p_bin; static int p_bomb; -static char_u *p_bh; -static char_u *p_bt; +static char_u *p_bh; +static char_u *p_bt; static int p_bl; static long p_channel; static int p_ci; static int p_cin; -static char_u *p_cink; -static char_u *p_cino; -static char_u *p_cinw; -static char_u *p_com; -static char_u *p_cms; -static char_u *p_cpt; -static char_u *p_cfu; -static char_u *p_ofu; -static char_u *p_tfu; +static char_u *p_cink; +static char_u *p_cino; +static char_u *p_cinw; +static char_u *p_com; +static char_u *p_cms; +static char_u *p_cpt; +static char_u *p_cfu; +static char_u *p_ofu; +static char_u *p_tfu; static int p_eol; static int p_fixeol; static int p_et; -static char_u *p_fenc; -static char_u *p_ff; -static char_u *p_fo; -static char_u *p_flp; -static char_u *p_ft; +static char_u *p_fenc; +static char_u *p_ff; +static char_u *p_fo; +static char_u *p_flp; +static char_u *p_ft; static long p_iminsert; static long p_imsearch; -static char_u *p_inex; -static char_u *p_inde; -static char_u *p_indk; -static char_u *p_fex; +static char_u *p_inex; +static char_u *p_inde; +static char_u *p_indk; +static char_u *p_fex; static int p_inf; -static char_u *p_isk; +static char_u *p_isk; static int p_lisp; static int p_ml; static int p_ma; static int p_mod; -static char_u *p_mps; -static char_u *p_nf; +static char_u *p_mps; +static char_u *p_nf; static int p_pi; -static char_u *p_qe; +static char_u *p_qe; static int p_ro; static int p_si; static long p_sts; -static char_u *p_sua; +static char_u *p_sua; static long p_sw; static int p_swf; static long p_smc; -static char_u *p_syn; -static char_u *p_spc; -static char_u *p_spf; -static char_u *p_spl; -static char_u *p_spo; +static char_u *p_syn; +static char_u *p_spc; +static char_u *p_spf; +static char_u *p_spl; +static char_u *p_spo; static long p_ts; static long p_tw; static int p_udf; static long p_wm; static char_u *p_vsts; static char_u *p_vts; -static char_u *p_keymap; +static char_u *p_keymap; // Saved values for when 'bin' is set. static int p_et_nobin; @@ -198,15 +198,15 @@ static long p_wm_nopaste; static char_u *p_vsts_nopaste; typedef struct vimoption { - char *fullname; // full option name - char *shortname; // permissible abbreviation + char *fullname; // full option name + char *shortname; // permissible abbreviation uint32_t flags; // see below - char_u *var; // global option: pointer to variable; - // window-local option: VAR_WIN; - // buffer-local option: global value + char_u *var; // global option: pointer to variable; + // window-local option: VAR_WIN; + // 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_u *def_val; // default values for variable (neovim!!) LastSet last_set; // script in which the option was last set } vimoption_T; @@ -314,12 +314,15 @@ static char *(p_csl_values[]) = { "slash", "backslash", NULL }; #endif static char *(p_icm_values[]) = { "nosplit", "split", NULL }; static char *(p_scl_values[]) = { "yes", "no", "auto", "auto:1", "auto:2", - "auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", "auto:9", - "yes:1", "yes:2", "yes:3", "yes:4", "yes:5", "yes:6", "yes:7", "yes:8", - "yes:9", "number", NULL }; + "auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", + "auto:9", + "yes:1", "yes:2", "yes:3", "yes:4", "yes:5", "yes:6", + "yes:7", "yes:8", + "yes:9", "number", NULL }; static char *(p_fdc_values[]) = { "auto", "auto:1", "auto:2", - "auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", "auto:9", - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL }; + "auto:3", "auto:4", "auto:5", "auto:6", "auto:7", "auto:8", + "auto:9", + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL }; /// All possible flags for 'shm'. static char_u SHM_ALL[] = { @@ -372,9 +375,9 @@ void set_init_1(bool clean_arg) */ { # ifdef UNIX - static char *(names[4]) = {"", "TMPDIR", "TEMP", "TMP"}; + static char *(names[4]) = { "", "TMPDIR", "TEMP", "TMP" }; # else - static char *(names[3]) = {"TMPDIR", "TEMP", "TMP"}; + static char *(names[3]) = { "TMPDIR", "TEMP", "TMP" }; # endif garray_T ga; opt_idx = findoption("backupskip"); @@ -426,8 +429,8 @@ void set_init_1(bool clean_arg) } { - char_u *cdpath; - char_u *buf; + char_u *cdpath; + char_u *buf; int i; int j; @@ -470,13 +473,13 @@ void set_init_1(bool clean_arg) set_string_default("printexpr", #ifdef UNIX "system(['lpr'] " - "+ (empty(&printdevice)?[]:['-P', &printdevice]) " - "+ [v:fname_in])" + "+ (empty(&printdevice)?[]:['-P', &printdevice]) " + "+ [v:fname_in])" ". delete(v:fname_in)" "+ v:shell_error", #elif defined(MSWIN) "system(['copy', v:fname_in, " - "empty(&printdevice)?'LPT1':&printdevice])" + "empty(&printdevice)?'LPT1':&printdevice])" ". delete(v:fname_in)", #else "", @@ -550,7 +553,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 = (char *)option_expand(opt_idx, NULL); } if (p != NULL) { p = xstrdup(p); @@ -584,8 +587,8 @@ void set_init_1(bool clean_arg) // in 'fileencodings' char_u *p = enc_locale(); if (p == NULL) { - // use utf-8 as 'default' if locale encoding can't be detected. - p = (char_u *)xmemdupz(S_LEN("utf-8")); + // use utf-8 as 'default' if locale encoding can't be detected. + p = (char_u *)xmemdupz(S_LEN("utf-8")); } fenc_default = p; @@ -605,7 +608,7 @@ void set_init_1(bool clean_arg) /// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL static void set_option_default(int opt_idx, int opt_flags) { - char_u *varp; // pointer to variable for current option + 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); @@ -624,7 +627,7 @@ static void set_option_default(int opt_idx, int opt_flags) *(char_u **)varp = options[opt_idx].def_val; options[opt_idx].flags &= ~P_ALLOCED; } - } else if (flags & P_NUM) { + } else if (flags & P_NUM) { if (options[opt_idx].indir == PV_SCROLL) { win_comp_scroll(curwin); } else { @@ -667,10 +670,9 @@ static void set_option_default(int opt_idx, int opt_flags) } /// Set all options (except terminal options) to their default value. -static void -set_options_default( - int opt_flags // OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL -) +/// +/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL +static void set_options_default(int opt_flags) { for (int i = 0; options[i].fullname; i++) { if (!(options[i].flags & P_NODEFAULT)) { @@ -710,8 +712,7 @@ static void set_string_default(const char *name, char *val, bool allocated) // For an option value that contains comma separated items, find "newval" in // "origval". Return NULL if not found. -static char_u *find_dup_item(char_u *origval, const char_u *newval, - uint32_t flags) +static char_u *find_dup_item(char_u *origval, const char_u *newval, uint32_t flags) FUNC_ATTR_NONNULL_ARG(2) { int bs = 0; @@ -827,9 +828,8 @@ void set_init_3(void) // 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 (fnamecmp(p, "csh") == 0 + || fnamecmp(p, "tcsh") == 0) { if (do_sp) { p_sp = (char_u *)"|& tee"; options[idx_sp].def_val = p_sp; @@ -847,8 +847,7 @@ void set_init_3(void) || fnamecmp(p, "bash") == 0 || fnamecmp(p, "fish") == 0 || fnamecmp(p, "ash") == 0 - || fnamecmp(p, "dash") == 0 - ) { + || fnamecmp(p, "dash") == 0) { // Always use POSIX shell style redirection if we reach this if (do_sp) { p_sp = (char_u *)"2>&1| tee"; @@ -933,28 +932,27 @@ void set_title_defaults(void) } } -// Parse 'arg' for option settings. -// -// 'arg' may be IObuff, but only when no errors can be present and option -// does not need to be expanded with option_expand(). -// "opt_flags": -// 0 for ":set" -// OPT_GLOBAL for ":setglobal" -// OPT_LOCAL for ":setlocal" and a modeline -// OPT_MODELINE for a modeline -// OPT_WINONLY to only set window-local options -// OPT_NOWIN to skip setting window-local options -// -// returns FAIL if an error is detected, OK otherwise -int do_set( - char_u *arg, // option string (may be written to!) - int opt_flags -) +/// Parse 'arg' for option settings. +/// +/// 'arg' may be IObuff, but only when no errors can be present and option +/// does not need to be expanded with option_expand(). +/// "opt_flags": +/// 0 for ":set" +/// OPT_GLOBAL for ":setglobal" +/// OPT_LOCAL for ":setlocal" and a modeline +/// OPT_MODELINE for a modeline +/// OPT_WINONLY to only set window-local options +/// OPT_NOWIN to skip setting window-local options +/// +/// @param arg option string (may be written to!) +/// +/// @return FAIL if an error is detected, OK otherwise +int do_set(char_u *arg, int opt_flags) { int opt_idx; - char_u *errmsg; + char_u *errmsg; char_u errbuf[80]; - char_u *startarg; + char_u *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 @@ -963,7 +961,7 @@ int do_set( varnumber_T value; int key; uint32_t flags; // flags for current option - char_u *varp = NULL; // pointer to variable for current option + char_u *varp = NULL; // pointer to variable for current option int did_show = false; // already showed one value int adding; // "opt+=arg" int prepending; // "opt^=arg" @@ -1099,8 +1097,9 @@ int do_set( /* Skip all options that are not window-local (used when showing * an already loaded buffer in a window). */ if ((opt_flags & OPT_WINONLY) - && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) + && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) { goto skip; + } // Skip all options that are window-local (used for :vimgrep). if ((opt_flags & OPT_NOWIN) && opt_idx >= 0 @@ -1115,8 +1114,7 @@ int do_set( goto skip; } if ((flags & P_MLE) && !p_mle) { - errmsg = (char_u *)N_( - "E992: Not allowed in a modeline when 'modelineexpr' is off"); + errmsg = (char_u *)N_("E992: Not allowed in a modeline when 'modelineexpr' is off"); goto skip; } // In diff mode some options are overruled. This avoids that @@ -1177,10 +1175,10 @@ int do_set( option_last_set_msg(options[opt_idx].last_set); } else if ((int)options[opt_idx].indir & PV_WIN) { option_last_set_msg(curwin->w_p_script_ctx[ - (int)options[opt_idx].indir & PV_MASK]); + (int)options[opt_idx].indir & PV_MASK]); } else if ((int)options[opt_idx].indir & PV_BUF) { option_last_set_msg(curbuf->b_p_script_ctx[ - (int)options[opt_idx].indir & PV_MASK]); + (int)options[opt_idx].indir & PV_MASK]); } } } else { @@ -1188,8 +1186,9 @@ int do_set( goto skip; } if (nextchar != '?' - && nextchar != NUL && !ascii_iswhite(afterchar)) + && nextchar != NUL && !ascii_iswhite(afterchar)) { errmsg = e_trailing; + } } else { int value_is_replaced = !prepending && !adding && !removing; int value_checked = false; @@ -1260,8 +1259,7 @@ int do_set( if ((long *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) { value = NO_LOCAL_UNDOLEVEL; } else { - value = *(long *)get_varp_scope( - &(options[opt_idx]), OPT_GLOBAL); + value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); } } else if (((long *)varp == &p_wc || (long *)varp == &p_wcm) @@ -1299,11 +1297,11 @@ int do_set( errbuf, sizeof(errbuf), opt_flags); } else if (opt_idx >= 0) { // String. - char_u *save_arg = NULL; - char_u *s = NULL; - char_u *oldval = NULL; // previous value if *varp - char_u *newval; - char_u *origval = NULL; + char_u *save_arg = NULL; + char_u *s = NULL; + char_u *oldval = NULL; // previous value if *varp + char_u *newval; + char_u *origval = NULL; char *saved_origval = NULL; char *saved_newval = NULL; unsigned newlen; @@ -1314,8 +1312,9 @@ int do_set( * with a local value the local value will be * reset, use the global value here. */ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 - && ((int)options[opt_idx].indir & PV_BOTH)) + && ((int)options[opt_idx].indir & PV_BOTH)) { varp = options[opt_idx].var; + } /* The old value is kept until we are sure that the * new value is valid. */ @@ -1349,8 +1348,7 @@ int do_set( newval = (char_u *)xstrdup((char *)newval); } } else if (nextchar == '<') { // set to global val - newval = vim_strsave(*(char_u **)get_varp_scope( - &(options[opt_idx]), OPT_GLOBAL)); + newval = vim_strsave(*(char_u **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL)); new_value_alloced = true; } else { arg++; // jump to after the '=' or ':' @@ -1378,16 +1376,13 @@ int do_set( *(char_u **)varp = empty_option; break; case 1: - *(char_u **)varp = vim_strsave( - (char_u *)"indent,eol"); + *(char_u **)varp = vim_strsave((char_u *)"indent,eol"); break; case 2: - *(char_u **)varp = vim_strsave( - (char_u *)"indent,eol,start"); + *(char_u **)varp = vim_strsave((char_u *)"indent,eol,start"); break; case 3: - *(char_u **)varp = vim_strsave( - (char_u *)"indent,eol,nostop"); + *(char_u **)varp = vim_strsave((char_u *)"indent,eol,nostop"); break; } xfree(oldval); @@ -1427,9 +1422,9 @@ int do_set( * Remove '>' before 'dir' and 'bdir', for * backwards compatibility with version 3.0 */ - else if ( *arg == '>' - && (varp == (char_u *)&p_dir - || varp == (char_u *)&p_bdir)) { + else if (*arg == '>' + && (varp == (char_u *)&p_dir + || varp == (char_u *)&p_bdir)) { arg++; } @@ -1464,8 +1459,9 @@ int do_set( || (s == newval && arg[2] != '\\'))) #endif - ) + ) { arg++; // remove backslash + } i = utfc_ptr2len(arg); if (i > 1) { // copy multibyte char @@ -1533,7 +1529,7 @@ int do_set( i--; } memmove(newval + i + comma, newval, - STRLEN(newval) + 1); + STRLEN(newval) + 1); memmove(newval, origval, (size_t)i); } else { i = (int)STRLEN(newval); @@ -1650,7 +1646,6 @@ int do_set( if (errmsg != NULL) { goto skip; } - } else { // key code option(FIXME(tarruda): Show a warning or something // similar) @@ -1719,15 +1714,13 @@ theend: return OK; } -// Call this when an option has been given a new value through a user command. -// Sets the P_WAS_SET flag and takes care of the P_INSECURE flag. -static void did_set_option( - int opt_idx, - int opt_flags, // possibly with OPT_MODELINE - int new_value, // value was replaced completely - int value_checked // value was checked to be safe, no need to - // set P_INSECURE -) +/// Call this when an option has been given a new value through a user command. +/// Sets the P_WAS_SET flag and takes care of the P_INSECURE flag. +/// +/// @param opt_flags possibly with OPT_MODELINE +/// @param new_value value was replaced completely +/// @param value_checked value was checked to be safe, no need to set P_INSECURE +static void did_set_option(int opt_idx, int opt_flags, int new_value, int value_checked) { options[opt_idx].flags |= P_WAS_SET; @@ -1796,12 +1789,10 @@ static void did_set_title(void) } } -// set_options_bin - called when 'bin' changes value. -void set_options_bin( - int oldval, - int newval, - int opt_flags // OPT_LOCAL and/or OPT_GLOBAL -) +/// set_options_bin - called when 'bin' changes value. +/// +/// @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 @@ -1859,7 +1850,7 @@ void set_options_bin( /// number, return -1. int get_shada_parameter(int type) { - char_u *p; + char_u *p; p = find_shada_parameter(type); if (p != NULL && ascii_isdigit(*p)) { @@ -1873,7 +1864,7 @@ 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; + char_u *p; for (p = p_shada; *p; p++) { if (*p == type) { @@ -2102,12 +2093,18 @@ static uint32_t *insecure_flag(win_T *const wp, int opt_idx, int opt_flags) if (opt_flags & OPT_LOCAL) { assert(wp != NULL); switch ((int)options[opt_idx].indir) { - case PV_STL: return &wp->w_p_stl_flags; - case PV_FDE: return &wp->w_p_fde_flags; - case PV_FDT: return &wp->w_p_fdt_flags; - case PV_INDE: return &wp->w_buffer->b_p_inde_flags; - case PV_FEX: return &wp->w_buffer->b_p_fex_flags; - case PV_INEX: return &wp->w_buffer->b_p_inex_flags; + case PV_STL: + return &wp->w_p_stl_flags; + case PV_FDE: + return &wp->w_p_fde_flags; + case PV_FDT: + return &wp->w_p_fdt_flags; + case PV_INDE: + return &wp->w_buffer->b_p_inde_flags; + case PV_FEX: + return &wp->w_buffer->b_p_fex_flags; + case PV_INEX: + return &wp->w_buffer->b_p_inex_flags; } } @@ -2125,23 +2122,19 @@ static void redraw_titles(void) static int shada_idx = -1; -// Set a string option to a new value (without checking the effect). -// The string is copied into allocated memory. -// if ("opt_idx" == -1) "name" is used, otherwise "opt_idx" is used. -// When "set_sid" is zero set the scriptID to current_sctx.sc_sid. When -// "set_sid" is SID_NONE don't set the scriptID. Otherwise set the scriptID to -// "set_sid". -void -set_string_option_direct( - const char *name, - int opt_idx, - const char_u *val, - int opt_flags, // OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL - int set_sid -) -{ - char_u *s; - char_u **varp; +/// Set a string option to a new value (without checking the effect). +/// The string is copied into allocated memory. +/// if ("opt_idx" == -1) "name" is used, otherwise "opt_idx" is used. +/// When "set_sid" is zero set the scriptID to current_sctx.sc_sid. When +/// "set_sid" is SID_NONE don't set the scriptID. Otherwise set the scriptID to +/// "set_sid". +/// +/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL +void set_string_option_direct(const char *name, int opt_idx, const char_u *val, int opt_flags, + int set_sid) +{ + char_u *s; + char_u **varp; int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; int idx = opt_idx; @@ -2158,7 +2151,7 @@ set_string_option_direct( return; } - assert((void *) options[idx].var != (void *) &p_shada); + assert((void *)options[idx].var != (void *)&p_shada); s = vim_strsave(val); { @@ -2198,13 +2191,12 @@ set_string_option_direct( } /// Set global value for string option when it's a local option. -static void -set_string_option_global( - int opt_idx, // option index - char_u **varp // pointer to option variable -) +/// +/// @param opt_idx option index +/// @param varp pointer to option variable +static void set_string_option_global(int opt_idx, char_u **varp) { - char_u **p, *s; + char_u **p, *s; // the global value is always allocated if (options[opt_idx].var == VAR_WIN) { @@ -2227,8 +2219,7 @@ set_string_option_global( /// #OPT_GLOBAL. /// /// @return NULL on success, error message on error. -static char *set_string_option(const int opt_idx, const char *const value, - const int opt_flags) +static 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 { if (options[opt_idx].var == NULL) { // don't set hidden option @@ -2236,12 +2227,11 @@ static char *set_string_option(const int opt_idx, const char *const value, } char *const s = xstrdup(value); - char **const varp = (char **)get_varp_scope( - &(options[opt_idx]), - ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 + char **const varp = (char **)get_varp_scope(&(options[opt_idx]), + ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 ? (((int)options[opt_idx].indir & PV_BOTH) ? OPT_GLOBAL : OPT_LOCAL) - : opt_flags)); + : opt_flags)); char *const oldval = *varp; *varp = s; @@ -2249,9 +2239,9 @@ static char *set_string_option(const int opt_idx, const char *const value, char *const saved_newval = xstrdup(s); int value_checked = false; - char *const r = (char *)did_set_string_option( - opt_idx, (char_u **)varp, (int)true, (char_u *)oldval, - NULL, 0, opt_flags, &value_checked); + char *const r = (char *)did_set_string_option(opt_idx, (char_u **)varp, (int)true, + (char_u *)oldval, + NULL, 0, opt_flags, &value_checked); if (r == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); } @@ -2315,23 +2305,23 @@ static bool valid_spellfile(const char_u *val) /// Handle string options that need some action to perform when changed. /// Returns NULL for success, or an error message for an error. -static char_u * -did_set_string_option( - int opt_idx, // index in options[] table - char_u **varp, // pointer to the option variable - bool new_value_alloced, // new value was allocated - char_u *oldval, // previous value of the option - char_u *errbuf, // buffer for errors, or NULL - size_t errbuflen, // length of errors buffer - int opt_flags, // OPT_LOCAL and/or OPT_GLOBAL - int *value_checked // value was checked to be safe, no - // need to set P_INSECURE -) -{ - char_u *errmsg = NULL; - char_u *s, *p; +/// +/// @param opt_idx index in options[] table +/// @param varp pointer to the option variable +/// @param new_value_alloced new value was allocated +/// @param oldval previous value of the option +/// @param errbuf buffer for errors, or NULL +/// @param errbuflen length of errors buffer +/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL +/// @param value_checked value was checked to be safe, no need to set P_INSECURE +static char_u *did_set_string_option(int opt_idx, char_u **varp, bool new_value_alloced, + char_u *oldval, char_u *errbuf, size_t errbuflen, + int opt_flags, int *value_checked) +{ + char_u *errmsg = NULL; + char_u *s, *p; int did_chartab = false; - char_u **gvarp; + char_u **gvarp; bool free_oldval = (options[opt_idx].flags & P_ALLOCED); bool value_changed = false; @@ -2345,7 +2335,7 @@ did_set_string_option( errmsg = e_secure; } else if (((options[opt_idx].flags & P_NFNAME) && vim_strpbrk(*varp, (char_u *)(secure ? "/\\*?[|;&<>\r\n" - : "/\\*?[<>\r\n")) != NULL) + : "/\\*?[<>\r\n")) != NULL) || ((options[opt_idx].flags & P_NDNAME) && vim_strpbrk(*varp, (char_u *)"*?[|;&<>\r\n") != NULL)) { // Check for a "normal" directory or file name in some options. Disallow a @@ -2353,7 +2343,7 @@ did_set_string_option( // 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_u *bkc = p_bkc; unsigned int *flags = &bkc_flags; if (opt_flags & OPT_LOCAL) { @@ -2407,6 +2397,8 @@ did_set_string_option( os_setenv("VIMRUNTIME", "", 1); didset_vimruntime = false; } + } else if (varp == &p_rtp || varp == &p_pp) { // 'runtimepath' 'packpath' + invalidate_search_path(); } else if (varp == &curwin->w_p_culopt || gvarp == &curwin->w_allbuf_opt.wo_culopt) { // 'cursorlineopt' if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK) { @@ -2493,13 +2485,14 @@ ambw_end: check_string_option(&p_bg); init_highlight(false, false); } - } else + } else { errmsg = e_invarg; + } } else if (varp == &p_wim) { // 'wildmode' if (check_opt_wim() == FAIL) { errmsg = e_invarg; } - // 'wildoptions' + // 'wildoptions' } else if (varp == &p_wop) { if (opt_strings_flags(p_wop, p_wop_values, &wop_flags, true) != OK) { errmsg = e_invarg; @@ -2513,7 +2506,7 @@ ambw_end: if (check_ei() == FAIL) { errmsg = e_invarg; } - // 'encoding', 'fileencoding' and 'makeencoding' + // 'encoding', 'fileencoding' and 'makeencoding' } else if (varp == &p_enc || gvarp == &p_fenc || gvarp == &p_menc) { if (gvarp == &p_fenc) { if (!MODIFIABLE(curbuf) && opt_flags != OPT_GLOBAL) { @@ -2684,7 +2677,7 @@ ambw_end: if (*p_vfile != NUL && verbose_open() == FAIL) { errmsg = e_invarg; } - // 'shada' + // 'shada' } else if (varp == &p_shada) { // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo // option. @@ -2692,7 +2685,7 @@ ambw_end: ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx) - : opt_idx); + : opt_idx); // Update free_oldval now that we have the opt_idx for 'shada', otherwise // 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. @@ -2721,8 +2714,9 @@ ambw_end: _("E526: Missing number after <%s>"), transchar_byte(*(s - 1))); errmsg = errbuf; - } else + } else { errmsg = (char_u *)""; + } break; } } @@ -2743,8 +2737,7 @@ ambw_end: } else if (gvarp == &p_sbr) { // 'showbreak' for (s = *varp; *s; ) { if (ptr2cells(s) != 1) { - errmsg = (char_u *)N_( - "E595: 'showbreak' contains unprintable or wide character"); + errmsg = (char_u *)N_("E595: 'showbreak' contains unprintable or wide character"); } MB_PTR_ADV(s); } @@ -2769,7 +2762,6 @@ ambw_end: stl_syntax &= ~flagval; } did_set_title(); - } else if (varp == &p_sel) { // 'selection' if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) { @@ -2888,8 +2880,9 @@ ambw_end: } else if (gvarp == &p_cpt) { // check if it is a valid value for 'complete' -- Acevedo for (s = *varp; *s; ) { - while (*s == ',' || *s == ' ') + while (*s == ',' || *s == ' ') { s++; + } if (!*s) { break; } @@ -2912,8 +2905,9 @@ ambw_end: _("E535: Illegal character after <%c>"), *--s); errmsg = errbuf; - } else + } else { errmsg = (char_u *)""; + } break; } } @@ -3024,8 +3018,7 @@ ambw_end: } } else if (gvarp == &p_cms) { // 'commentstring' if (**varp != NUL && strstr((char *)(*varp), "%s") == NULL) { - errmsg = (char_u *)N_( - "E537: 'commentstring' must be empty or contain %s"); + errmsg = (char_u *)N_("E537: 'commentstring' must be empty or contain %s"); } } else if (varp == &p_fdo) { // 'foldopen' if (opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true) != OK) { @@ -3068,11 +3061,11 @@ ambw_end: } else if (gvarp == &p_cino) { // 'cinoptions' // TODO(vim): recognize errors parse_cino(curbuf); - // inccommand + // inccommand } else if (varp == &p_icm) { - if (check_opt_strings(p_icm, p_icm_values, false) != OK) { - errmsg = e_invarg; - } + if (check_opt_strings(p_icm, p_icm_values, false) != OK) { + errmsg = e_invarg; + } } else if (gvarp == &p_ft) { if (!valid_filetype(*varp)) { errmsg = e_invarg; @@ -3274,7 +3267,7 @@ ambw_end: } if (varp == &(curwin->w_s->b_p_spl)) { char_u fname[200]; - char_u *q = curwin->w_s->b_p_spl; + char_u *q = curwin->w_s->b_p_spl; // Skip the first name if it is "cjk". if (STRNCMP(q, "cjk,", 4) == 0) { @@ -3305,8 +3298,9 @@ ambw_end: } if (curwin->w_curswant != MAXCOL - && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) + && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) { curwin->w_set_curswant = true; + } check_redraw(options[opt_idx].flags); @@ -3334,8 +3328,7 @@ int check_signcolumn(char_u *val) && !STRNCMP(val, "auto:", 5) && ascii_isdigit(val[5]) && val[6] == '-' - && ascii_isdigit(val[7]) - ) { + && ascii_isdigit(val[7])) { int min = val[5] - '0'; int max = val[7] - '0'; if (min < 1 || max < 2 || min > 8 || max > 9 || min >= max) { @@ -3352,7 +3345,7 @@ int check_signcolumn(char_u *val) /// @return error message, NULL if it's OK. char_u *check_colorcolumn(win_T *wp) { - char_u *s; + char_u *s; int col; unsigned int count = 0; int color_cols[256]; @@ -3446,9 +3439,9 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set) int multispace_len = 0; // Length of lcs-multispace string struct chars_tab { - int *cp; ///< char value - char *name; ///< char id - int def; ///< default value + int *cp; ///< char value + char *name; ///< char id + int def; ///< default value }; struct chars_tab *tab; @@ -3658,8 +3651,9 @@ char_u *check_stl_option(char_u *s) } if (*s == '.') { s++; - while (*s && ascii_isdigit(*s)) + while (*s && ascii_isdigit(*s)) { s++; + } } if (*s == '(') { groupdepth++; @@ -3687,7 +3681,7 @@ char_u *check_stl_option(char_u *s) static char_u *did_set_spell_option(bool is_spellfile) { - char_u *errmsg = NULL; + char_u *errmsg = NULL; if (is_spellfile) { int l = (int)STRLEN(curwin->w_s->b_p_spf); @@ -3714,8 +3708,8 @@ static char_u *did_set_spell_option(bool is_spellfile) static char_u *compile_cap_prog(synblock_T *synblock) FUNC_ATTR_NONNULL_ALL { - regprog_T *rp = synblock->b_cap_prog; - char_u *re; + 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; @@ -3814,8 +3808,7 @@ static void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx) /// @param[in] opt_flags OPT_LOCAL and/or OPT_GLOBAL. /// /// @return NULL on success, error message on error. -static char *set_bool_option(const int opt_idx, char_u *const varp, - const int value, +static char *set_bool_option(const int opt_idx, char_u *const varp, const int value, const int opt_flags) { int old_value = *(int *)varp; @@ -3840,7 +3833,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, if ((int *)varp == &p_force_on && p_force_on == false) { p_force_on = true; return (char *)e_unsupportedoption; - // Ensure that options set to p_force_off cannot be enabled. + // Ensure that options set to p_force_off cannot be enabled. } else if ((int *)varp == &p_force_off && p_force_off == true) { p_force_off = false; return (char *)e_unsupportedoption; @@ -3853,7 +3846,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, } else if ((int *)varp == &curwin->w_p_cul && !value && old_value) { // 'cursorline' reset_cursorline(); - // 'undofile' + // 'undofile' } else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf) { // Only take action when the option was set. When reset we do not // delete the undo file, the option may be set again without making @@ -3917,7 +3910,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, } } else if ((int *)varp == &p_terse) { // when 'terse' is set change 'shortmess' - char_u *p; + char_u *p; p = vim_strchr(p_shm, SHM_SEARCH); @@ -3954,8 +3947,8 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, // when 'hlsearch' is set or reset: reset no_hlsearch set_no_hlsearch(false); } else if ((int *)varp == &curwin->w_p_scb) { - // when 'scrollbind' is set: snapshot the current position to avoid a jump - // at the end of normal_cmd() + // when 'scrollbind' is set: snapshot the current position to avoid a jump + // at the end of normal_cmd() if (curwin->w_p_scb) { do_check_scrollbind(false); curwin->w_scbind_pos = curwin->w_topline; @@ -4025,7 +4018,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, } } else if ((int *)varp == &curwin->w_p_spell) { // 'spell' if (curwin->w_p_spell) { - char_u *errmsg = did_set_spelllang(curwin); + char_u *errmsg = did_set_spelllang(curwin); if (errmsg != NULL) { EMSG(_(errmsg)); } @@ -4054,8 +4047,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, /* Arabic requires a utf-8 encoding, inform the user if its not * set. */ if (STRCMP(p_enc, "utf-8") != 0) { - static char *w_arabic = N_( - "W17: Arabic requires UTF-8, do ':set encoding=utf-8'"); + static char *w_arabic = N_("W17: Arabic requires UTF-8, do ':set encoding=utf-8'"); msg_source(HL_ATTR(HLF_W)); msg_attr(_(w_arabic), HL_ATTR(HLF_W)); @@ -4115,7 +4107,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, set_vim_var_string(VV_OPTION_OLD, buf_old, -1); set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); apply_autocmds(EVENT_OPTIONSET, - (char_u *) options[opt_idx].fullname, + (char_u *)options[opt_idx].fullname, NULL, false, NULL); reset_v_option_vars(); } @@ -4145,13 +4137,13 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, /// @param[in] opt_flags OPT_LOCAL, OPT_GLOBAL or OPT_MODELINE. /// /// @return NULL on success, error message on error. -static char *set_num_option(int opt_idx, char_u *varp, long value, - char_u *errbuf, size_t errbuflen, int opt_flags) +static char *set_num_option(int opt_idx, char_u *varp, long value, char_u *errbuf, size_t errbuflen, + int opt_flags) { - char_u *errmsg = NULL; + char_u *errmsg = NULL; long old_value = *(long *)varp; long old_Rows = Rows; // remember old Rows - long *pp = (long *)varp; + long *pp = (long *)varp; // Disallow changing some options from secure mode. if ((secure || sandbox != 0) @@ -4161,7 +4153,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, // Many number options assume their value is in the signed int range. if (value < INT_MIN || value > INT_MAX) { - return (char *)e_invarg; + return (char *)e_invarg; } // Options that need some validation. @@ -4425,7 +4417,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, if (p_lines < min_rows() && full_screen) { if (errbuf != NULL) { vim_snprintf((char *)errbuf, errbuflen, - _("E593: Need at least %d lines"), min_rows()); + _("E593: Need at least %d lines"), min_rows()); errmsg = errbuf; } p_lines = min_rows(); @@ -4433,7 +4425,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, if (p_columns < MIN_COLUMNS && full_screen) { if (errbuf != NULL) { vim_snprintf((char *)errbuf, errbuflen, - _("E594: Need at least %d columns"), MIN_COLUMNS); + _("E594: Need at least %d columns"), MIN_COLUMNS); errmsg = errbuf; } p_columns = MIN_COLUMNS; @@ -4478,7 +4470,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, } win_comp_scroll(curwin); } else if (curwin->w_p_scr <= 0) { - // If 'scroll' became invalid because of a side effect silently adjust it. + // If 'scroll' became invalid because of a side effect silently adjust it. curwin->w_p_scr = 1; } else { // curwin->w_p_scr > curwin->w_height curwin->w_p_scr = curwin->w_height; @@ -4514,7 +4506,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, set_vim_var_string(VV_OPTION_OLD, buf_old, -1); set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); apply_autocmds(EVENT_OPTIONSET, - (char_u *) options[opt_idx].fullname, + (char_u *)options[opt_idx].fullname, NULL, false, NULL); reset_v_option_vars(); } @@ -4534,8 +4526,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, return (char *)errmsg; } -static void trigger_optionsset_string(int opt_idx, int opt_flags, - char *oldval, char *newval) +static void trigger_optionsset_string(int opt_idx, int opt_flags, char *oldval, char *newval) { // Don't do this recursively. if (oldval != NULL @@ -4658,8 +4649,8 @@ bool is_tty_option(const char *name) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { return (name[0] == 't' && name[1] == '_') - || strequal(name, "term") - || strequal(name, "ttytype"); + || strequal(name, "term") + || strequal(name, "ttytype"); } #define TCO_BUFFER_SIZE 8 @@ -4738,18 +4729,15 @@ static int findoption(const char *const arg) /// Gets the value for an option. /// +/// @param stringval NULL when only checking existence +/// /// @returns: /// Number or Toggle option: 1, *numval gets value. /// String option: 0, *stringval gets allocated string. /// Hidden Number or Toggle option: -1. /// hidden String option: -2. /// unknown option: -3. -int get_option_value( - const char *name, - long *numval, - char_u **stringval, ///< NULL when only checking existence - int opt_flags -) +int get_option_value(const char *name, long *numval, char_u **stringval, int opt_flags) { if (get_tty_option(name, (char **)stringval)) { return 0; @@ -4783,7 +4771,7 @@ int get_option_value( if ((int *)varp == &curbuf->b_changed) { *numval = curbufIsChanged(); } else { - *numval = (long) *(int *)varp; // NOLINT(whitespace/cast) + *numval = (long)*(int *)varp; // NOLINT(whitespace/cast) } } return 1; @@ -4805,11 +4793,7 @@ int get_option_value( // see SOPT_* in option_defs.h for other flags // // Possible opt_type values: see SREQ_* in option_defs.h -int get_option_value_strict(char *name, - int64_t *numval, - char **stringval, - int opt_type, - void *from) +int get_option_value_strict(char *name, int64_t *numval, char **stringval, int opt_type, void *from) { if (get_tty_option(name, stringval)) { return SOPT_STRING | SOPT_GLOBAL; @@ -4925,8 +4909,8 @@ int get_option_value_strict(char *name, /// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both). /// /// @return NULL on success, error message on error. -char *set_option_value(const char *const name, const long number, - const char *const string, const int opt_flags) +char *set_option_value(const char *const name, const long number, const char *const string, + const int opt_flags) FUNC_ATTR_NONNULL_ARG(1) { if (is_tty_option(name)) { @@ -4934,7 +4918,7 @@ char *set_option_value(const char *const name, const long number, } int opt_idx; - char_u *varp; + char_u *varp; opt_idx = findoption(name); if (opt_idx < 0) { @@ -4994,7 +4978,7 @@ int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt) // add_termcap_entry(). if (len >= 4 && arg[0] == 't' && arg[1] == '_') { key = TERMCAP2KEY(arg[2], arg[3]); - } else if (has_lt) { + } else if (has_lt) { arg--; // put arg at the '<' modifiers = 0; key = find_special_key(&arg, len + 1, &modifiers, true, true, false); @@ -5012,15 +4996,13 @@ static int find_key_option(const char_u *arg, bool has_lt) /// if 'all' == 0: show changed options /// if 'all' == 1: show all normal options -static void -showoptions( - int all, - int opt_flags // OPT_LOCAL and/or OPT_GLOBAL -) +/// +/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL +static void showoptions(int all, int opt_flags) { - vimoption_T *p; + vimoption_T *p; int col; - char_u *varp; + char_u *varp; int item_count; int run; int row, rows; @@ -5155,13 +5137,11 @@ void ui_refresh_options(void) /// showoneopt: show the value of one option /// must not be called with a hidden option! -static void -showoneopt( - vimoption_T *p, - int opt_flags // OPT_LOCAL or OPT_GLOBAL -) +/// +/// @param opt_flags OPT_LOCAL or OPT_GLOBAL +static void showoneopt(vimoption_T *p, int opt_flags) { - char_u *varp; + char_u *varp; int save_silent = silent_mode; silent_mode = false; @@ -5212,11 +5192,11 @@ showoneopt( /// Return FAIL on error, OK otherwise. int makeset(FILE *fd, int opt_flags, int local_only) { - vimoption_T *p; - char_u *varp; // currently used value - char_u *varp_fresh; // local value - char_u *varp_local = NULL; // fresh value - char *cmd; + vimoption_T *p; + char_u *varp; // currently used value + char_u *varp_fresh; // local value + char_u *varp_local = NULL; // fresh value + char *cmd; int round; int pri; @@ -5340,21 +5320,20 @@ int makefoldset(FILE *fd) || 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_u **valuep, uint64_t flags) { - char_u *s; - char_u *buf = NULL; - char_u *part = NULL; - char_u *p; + char_u *s; + char_u *buf = NULL; + char_u *part = NULL; + char_u *p; if (fprintf(fd, "%s %s=", cmd, name) < 0) { return FAIL; @@ -5392,15 +5371,15 @@ static int put_setstring(FILE *fd, char *cmd, char *name, } p = buf; while (*p != NUL) { - // for each comma separated option part, append value to - // the option, :set rtp+=value - if (fprintf(fd, "%s %s+=", cmd, name) < 0) { - goto fail; - } - (void)copy_option_part(&p, part, size, ","); - if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL) { - goto fail; - } + // for each comma separated option part, append value to + // the option, :set rtp+=value + if (fprintf(fd, "%s %s+=", cmd, name) < 0) { + goto fail; + } + (void)copy_option_part(&p, part, size, ","); + if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL) { + goto fail; + } } xfree(buf); xfree(part); @@ -5516,124 +5495,149 @@ void unset_global_local_option(char *name, void *from) switch ((int)p->indir) { - // global option with local value: use local value if it's been set + // global option with local value: use local value if it's been set + case PV_EP: + clear_string_option(&buf->b_p_ep); + break; + case PV_KP: + clear_string_option(&buf->b_p_kp); + break; + case PV_PATH: + clear_string_option(&buf->b_p_path); + break; + case PV_AR: + buf->b_p_ar = -1; + break; + case PV_BKC: + clear_string_option(&buf->b_p_bkc); + buf->b_bkc_flags = 0; + break; + case PV_TAGS: + clear_string_option(&buf->b_p_tags); + break; + case PV_TC: + clear_string_option(&buf->b_p_tc); + buf->b_tc_flags = 0; + break; + case PV_SISO: + curwin->w_p_siso = -1; + break; + case PV_SO: + curwin->w_p_so = -1; + break; + case PV_DEF: + clear_string_option(&buf->b_p_def); + break; + case PV_INC: + clear_string_option(&buf->b_p_inc); + break; + case PV_DICT: + clear_string_option(&buf->b_p_dict); + break; + case PV_TSR: + clear_string_option(&buf->b_p_tsr); + break; + case PV_FP: + clear_string_option(&buf->b_p_fp); + break; + case PV_EFM: + clear_string_option(&buf->b_p_efm); + break; + case PV_GP: + clear_string_option(&buf->b_p_gp); + break; + case PV_MP: + clear_string_option(&buf->b_p_mp); + break; + case PV_SBR: + clear_string_option(&((win_T *)from)->w_p_sbr); + break; + case PV_STL: + clear_string_option(&((win_T *)from)->w_p_stl); + break; + case PV_UL: + buf->b_p_ul = NO_LOCAL_UNDOLEVEL; + break; + case PV_LW: + clear_string_option(&buf->b_p_lw); + break; + case PV_MENC: + clear_string_option(&buf->b_p_menc); + break; + 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); + 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); + break; + } +} + +/// Get pointer to option variable, depending on local or global scope. +static char_u *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 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); + case PV_EFM: + return (char_u *)&(curbuf->b_p_efm); + case PV_GP: + return (char_u *)&(curbuf->b_p_gp); + case PV_MP: + return (char_u *)&(curbuf->b_p_mp); case PV_EP: - clear_string_option(&buf->b_p_ep); - break; + return (char_u *)&(curbuf->b_p_ep); case PV_KP: - clear_string_option(&buf->b_p_kp); - break; + return (char_u *)&(curbuf->b_p_kp); case PV_PATH: - clear_string_option(&buf->b_p_path); - break; + return (char_u *)&(curbuf->b_p_path); case PV_AR: - buf->b_p_ar = -1; - break; - case PV_BKC: - clear_string_option(&buf->b_p_bkc); - buf->b_bkc_flags = 0; - break; + return (char_u *)&(curbuf->b_p_ar); case PV_TAGS: - clear_string_option(&buf->b_p_tags); - break; + return (char_u *)&(curbuf->b_p_tags); case PV_TC: - clear_string_option(&buf->b_p_tc); - buf->b_tc_flags = 0; - break; + return (char_u *)&(curbuf->b_p_tc); case PV_SISO: - curwin->w_p_siso = -1; - break; + return (char_u *)&(curwin->w_p_siso); case PV_SO: - curwin->w_p_so = -1; - break; + return (char_u *)&(curwin->w_p_so); case PV_DEF: - clear_string_option(&buf->b_p_def); - break; + return (char_u *)&(curbuf->b_p_def); case PV_INC: - clear_string_option(&buf->b_p_inc); - break; + return (char_u *)&(curbuf->b_p_inc); case PV_DICT: - clear_string_option(&buf->b_p_dict); - break; + return (char_u *)&(curbuf->b_p_dict); case PV_TSR: - clear_string_option(&buf->b_p_tsr); - break; - case PV_FP: - clear_string_option(&buf->b_p_fp); - break; - case PV_EFM: - clear_string_option(&buf->b_p_efm); - break; - case PV_GP: - clear_string_option(&buf->b_p_gp); - break; - case PV_MP: - clear_string_option(&buf->b_p_mp); - break; + return (char_u *)&(curbuf->b_p_tsr); + case PV_TFU: + return (char_u *)&(curbuf->b_p_tfu); case PV_SBR: - clear_string_option(&((win_T *)from)->w_p_sbr); - break; + return (char_u *)&(curwin->w_p_sbr); case PV_STL: - clear_string_option(&((win_T *)from)->w_p_stl); - break; + return (char_u *)&(curwin->w_p_stl); case PV_UL: - buf->b_p_ul = NO_LOCAL_UNDOLEVEL; - break; + return (char_u *)&(curbuf->b_p_ul); case PV_LW: - clear_string_option(&buf->b_p_lw); - break; + return (char_u *)&(curbuf->b_p_lw); + case PV_BKC: + return (char_u *)&(curbuf->b_p_bkc); case PV_MENC: - clear_string_option(&buf->b_p_menc); - break; - 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); - break; + return (char_u *)&(curbuf->b_p_menc); 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); - break; - } -} - -/// Get pointer to option variable, depending on local or global scope. -static char_u *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 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); - case PV_EFM: return (char_u *)&(curbuf->b_p_efm); - case PV_GP: return (char_u *)&(curbuf->b_p_gp); - case PV_MP: return (char_u *)&(curbuf->b_p_mp); - case PV_EP: return (char_u *)&(curbuf->b_p_ep); - case PV_KP: return (char_u *)&(curbuf->b_p_kp); - case PV_PATH: return (char_u *)&(curbuf->b_p_path); - case PV_AR: return (char_u *)&(curbuf->b_p_ar); - case PV_TAGS: return (char_u *)&(curbuf->b_p_tags); - case PV_TC: return (char_u *)&(curbuf->b_p_tc); - case PV_SISO: return (char_u *)&(curwin->w_p_siso); - case PV_SO: return (char_u *)&(curwin->w_p_so); - case PV_DEF: return (char_u *)&(curbuf->b_p_def); - case PV_INC: return (char_u *)&(curbuf->b_p_inc); - case PV_DICT: return (char_u *)&(curbuf->b_p_dict); - case PV_TSR: return (char_u *)&(curbuf->b_p_tsr); - case PV_TFU: return (char_u *)&(curbuf->b_p_tfu); - case PV_SBR: return (char_u *)&(curwin->w_p_sbr); - case PV_STL: return (char_u *)&(curwin->w_p_stl); - case PV_UL: return (char_u *)&(curbuf->b_p_ul); - case PV_LW: return (char_u *)&(curbuf->b_p_lw); - case PV_BKC: return (char_u *)&(curbuf->b_p_bkc); - case PV_MENC: return (char_u *)&(curbuf->b_p_menc); - case PV_FCS: return (char_u *)&(curwin->w_p_fcs); - case PV_LCS: return (char_u *)&(curwin->w_p_lcs); + return (char_u *)&(curwin->w_p_fcs); + case PV_LCS: + return (char_u *)&(curwin->w_p_lcs); } return NULL; // "cannot happen" } @@ -5649,163 +5653,290 @@ static char_u *get_varp(vimoption_T *p) } switch ((int)p->indir) { - case PV_NONE: return p->var; + case PV_NONE: + return p->var; // global option with local value: use local value if it's been set - case PV_EP: return *curbuf->b_p_ep != NUL + case PV_EP: + return *curbuf->b_p_ep != NUL ? (char_u *)&curbuf->b_p_ep : p->var; - case PV_KP: return *curbuf->b_p_kp != NUL + case PV_KP: + return *curbuf->b_p_kp != NUL ? (char_u *)&curbuf->b_p_kp : p->var; - case PV_PATH: return *curbuf->b_p_path != NUL + case PV_PATH: + return *curbuf->b_p_path != NUL ? (char_u *)&(curbuf->b_p_path) : p->var; - case PV_AR: return curbuf->b_p_ar >= 0 + case PV_AR: + return curbuf->b_p_ar >= 0 ? (char_u *)&(curbuf->b_p_ar) : p->var; - case PV_TAGS: return *curbuf->b_p_tags != NUL + case PV_TAGS: + return *curbuf->b_p_tags != NUL ? (char_u *)&(curbuf->b_p_tags) : p->var; - case PV_TC: return *curbuf->b_p_tc != NUL + case PV_TC: + return *curbuf->b_p_tc != NUL ? (char_u *)&(curbuf->b_p_tc) : p->var; - case PV_SISO: return curwin->w_p_siso >= 0 + case PV_SISO: + return curwin->w_p_siso >= 0 ? (char_u *)&(curwin->w_p_siso) : p->var; - case PV_SO: return curwin->w_p_so >= 0 + case PV_SO: + return curwin->w_p_so >= 0 ? (char_u *)&(curwin->w_p_so) : p->var; - case PV_BKC: return *curbuf->b_p_bkc != NUL + case PV_BKC: + return *curbuf->b_p_bkc != NUL ? (char_u *)&(curbuf->b_p_bkc) : p->var; - case PV_DEF: return *curbuf->b_p_def != NUL + case PV_DEF: + return *curbuf->b_p_def != NUL ? (char_u *)&(curbuf->b_p_def) : p->var; - case PV_INC: return *curbuf->b_p_inc != NUL + case PV_INC: + return *curbuf->b_p_inc != NUL ? (char_u *)&(curbuf->b_p_inc) : p->var; - case PV_DICT: return *curbuf->b_p_dict != NUL + case PV_DICT: + return *curbuf->b_p_dict != NUL ? (char_u *)&(curbuf->b_p_dict) : p->var; - case PV_TSR: return *curbuf->b_p_tsr != NUL + case PV_TSR: + return *curbuf->b_p_tsr != NUL ? (char_u *)&(curbuf->b_p_tsr) : p->var; - case PV_FP: return *curbuf->b_p_fp != NUL + case PV_FP: + return *curbuf->b_p_fp != NUL ? (char_u *)&(curbuf->b_p_fp) : p->var; - case PV_EFM: return *curbuf->b_p_efm != NUL + case PV_EFM: + return *curbuf->b_p_efm != NUL ? (char_u *)&(curbuf->b_p_efm) : p->var; - case PV_GP: return *curbuf->b_p_gp != NUL + case PV_GP: + return *curbuf->b_p_gp != NUL ? (char_u *)&(curbuf->b_p_gp) : p->var; - case PV_MP: return *curbuf->b_p_mp != NUL + case PV_MP: + return *curbuf->b_p_mp != NUL ? (char_u *)&(curbuf->b_p_mp) : p->var; - case PV_SBR: return *curwin->w_p_sbr != NUL + case PV_SBR: + return *curwin->w_p_sbr != NUL ? (char_u *)&(curwin->w_p_sbr) : p->var; - case PV_STL: return *curwin->w_p_stl != NUL + case PV_STL: + return *curwin->w_p_stl != NUL ? (char_u *)&(curwin->w_p_stl) : p->var; - case PV_UL: return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL + case PV_UL: + return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL ? (char_u *)&(curbuf->b_p_ul) : p->var; - case PV_LW: return *curbuf->b_p_lw != NUL + case PV_LW: + return *curbuf->b_p_lw != NUL ? (char_u *)&(curbuf->b_p_lw) : p->var; - case PV_MENC: return *curbuf->b_p_menc != NUL + case PV_MENC: + return *curbuf->b_p_menc != NUL ? (char_u *)&(curbuf->b_p_menc) : p->var; - case PV_FCS: return *curwin->w_p_fcs != NUL + case PV_FCS: + return *curwin->w_p_fcs != NUL ? (char_u *)&(curwin->w_p_fcs) : p->var; - case PV_LCS: return *curwin->w_p_lcs != NUL + case PV_LCS: + return *curwin->w_p_lcs != NUL ? (char_u *)&(curwin->w_p_lcs) : p->var; - case PV_ARAB: return (char_u *)&(curwin->w_p_arab); - case PV_LIST: return (char_u *)&(curwin->w_p_list); - case PV_SPELL: return (char_u *)&(curwin->w_p_spell); - case PV_CUC: return (char_u *)&(curwin->w_p_cuc); - case PV_CUL: return (char_u *)&(curwin->w_p_cul); - case PV_CULOPT: return (char_u *)&(curwin->w_p_culopt); - case PV_CC: return (char_u *)&(curwin->w_p_cc); - case PV_DIFF: return (char_u *)&(curwin->w_p_diff); - case PV_FDC: return (char_u *)&(curwin->w_p_fdc); - case PV_FEN: return (char_u *)&(curwin->w_p_fen); - case PV_FDI: return (char_u *)&(curwin->w_p_fdi); - case PV_FDL: return (char_u *)&(curwin->w_p_fdl); - case PV_FDM: return (char_u *)&(curwin->w_p_fdm); - case PV_FML: return (char_u *)&(curwin->w_p_fml); - case PV_FDN: return (char_u *)&(curwin->w_p_fdn); - case PV_FDE: return (char_u *)&(curwin->w_p_fde); - case PV_FDT: return (char_u *)&(curwin->w_p_fdt); - case PV_FMR: return (char_u *)&(curwin->w_p_fmr); - case PV_NU: return (char_u *)&(curwin->w_p_nu); - case PV_RNU: return (char_u *)&(curwin->w_p_rnu); - case PV_NUW: return (char_u *)&(curwin->w_p_nuw); - case PV_WFH: return (char_u *)&(curwin->w_p_wfh); - case PV_WFW: return (char_u *)&(curwin->w_p_wfw); - case PV_PVW: return (char_u *)&(curwin->w_p_pvw); - case PV_RL: return (char_u *)&(curwin->w_p_rl); - case PV_RLC: return (char_u *)&(curwin->w_p_rlc); - case PV_SCROLL: return (char_u *)&(curwin->w_p_scr); - case PV_WRAP: return (char_u *)&(curwin->w_p_wrap); - case PV_LBR: return (char_u *)&(curwin->w_p_lbr); - case PV_BRI: return (char_u *)&(curwin->w_p_bri); - case PV_BRIOPT: return (char_u *)&(curwin->w_p_briopt); - case PV_SCBIND: return (char_u *)&(curwin->w_p_scb); - case PV_CRBIND: return (char_u *)&(curwin->w_p_crb); - case PV_COCU: return (char_u *)&(curwin->w_p_cocu); - case PV_COLE: return (char_u *)&(curwin->w_p_cole); - - case PV_AI: return (char_u *)&(curbuf->b_p_ai); - case PV_BIN: return (char_u *)&(curbuf->b_p_bin); - case PV_BOMB: return (char_u *)&(curbuf->b_p_bomb); - case PV_BH: return (char_u *)&(curbuf->b_p_bh); - case PV_BT: return (char_u *)&(curbuf->b_p_bt); - case PV_BL: return (char_u *)&(curbuf->b_p_bl); - case PV_CHANNEL:return (char_u *)&(curbuf->b_p_channel); - case PV_CI: return (char_u *)&(curbuf->b_p_ci); - case PV_CIN: return (char_u *)&(curbuf->b_p_cin); - case PV_CINK: return (char_u *)&(curbuf->b_p_cink); - case PV_CINO: return (char_u *)&(curbuf->b_p_cino); - case PV_CINW: return (char_u *)&(curbuf->b_p_cinw); - case PV_COM: return (char_u *)&(curbuf->b_p_com); - case PV_CMS: return (char_u *)&(curbuf->b_p_cms); - case PV_CPT: return (char_u *)&(curbuf->b_p_cpt); + case PV_ARAB: + return (char_u *)&(curwin->w_p_arab); + case PV_LIST: + return (char_u *)&(curwin->w_p_list); + case PV_SPELL: + return (char_u *)&(curwin->w_p_spell); + case PV_CUC: + return (char_u *)&(curwin->w_p_cuc); + case PV_CUL: + return (char_u *)&(curwin->w_p_cul); + case PV_CULOPT: + return (char_u *)&(curwin->w_p_culopt); + case PV_CC: + return (char_u *)&(curwin->w_p_cc); + case PV_DIFF: + return (char_u *)&(curwin->w_p_diff); + case PV_FDC: + return (char_u *)&(curwin->w_p_fdc); + case PV_FEN: + return (char_u *)&(curwin->w_p_fen); + case PV_FDI: + return (char_u *)&(curwin->w_p_fdi); + case PV_FDL: + return (char_u *)&(curwin->w_p_fdl); + case PV_FDM: + return (char_u *)&(curwin->w_p_fdm); + case PV_FML: + return (char_u *)&(curwin->w_p_fml); + case PV_FDN: + return (char_u *)&(curwin->w_p_fdn); + case PV_FDE: + return (char_u *)&(curwin->w_p_fde); + case PV_FDT: + return (char_u *)&(curwin->w_p_fdt); + case PV_FMR: + return (char_u *)&(curwin->w_p_fmr); + case PV_NU: + return (char_u *)&(curwin->w_p_nu); + case PV_RNU: + return (char_u *)&(curwin->w_p_rnu); + case PV_NUW: + return (char_u *)&(curwin->w_p_nuw); + case PV_WFH: + return (char_u *)&(curwin->w_p_wfh); + case PV_WFW: + return (char_u *)&(curwin->w_p_wfw); + case PV_PVW: + return (char_u *)&(curwin->w_p_pvw); + case PV_RL: + return (char_u *)&(curwin->w_p_rl); + case PV_RLC: + return (char_u *)&(curwin->w_p_rlc); + case PV_SCROLL: + return (char_u *)&(curwin->w_p_scr); + case PV_WRAP: + return (char_u *)&(curwin->w_p_wrap); + case PV_LBR: + return (char_u *)&(curwin->w_p_lbr); + case PV_BRI: + return (char_u *)&(curwin->w_p_bri); + case PV_BRIOPT: + return (char_u *)&(curwin->w_p_briopt); + case PV_SCBIND: + return (char_u *)&(curwin->w_p_scb); + case PV_CRBIND: + return (char_u *)&(curwin->w_p_crb); + case PV_COCU: + return (char_u *)&(curwin->w_p_cocu); + case PV_COLE: + return (char_u *)&(curwin->w_p_cole); + + case PV_AI: + return (char_u *)&(curbuf->b_p_ai); + case PV_BIN: + return (char_u *)&(curbuf->b_p_bin); + case PV_BOMB: + return (char_u *)&(curbuf->b_p_bomb); + case PV_BH: + return (char_u *)&(curbuf->b_p_bh); + case PV_BT: + return (char_u *)&(curbuf->b_p_bt); + case PV_BL: + return (char_u *)&(curbuf->b_p_bl); + case PV_CHANNEL: + return (char_u *)&(curbuf->b_p_channel); + case PV_CI: + return (char_u *)&(curbuf->b_p_ci); + case PV_CIN: + return (char_u *)&(curbuf->b_p_cin); + case PV_CINK: + return (char_u *)&(curbuf->b_p_cink); + case PV_CINO: + return (char_u *)&(curbuf->b_p_cino); + case PV_CINW: + return (char_u *)&(curbuf->b_p_cinw); + case PV_COM: + return (char_u *)&(curbuf->b_p_com); + case PV_CMS: + return (char_u *)&(curbuf->b_p_cms); + case PV_CPT: + return (char_u *)&(curbuf->b_p_cpt); # ifdef BACKSLASH_IN_FILENAME - case PV_CSL: return (char_u *)&(curbuf->b_p_csl); + case PV_CSL: + return (char_u *)&(curbuf->b_p_csl); # endif - case PV_CFU: return (char_u *)&(curbuf->b_p_cfu); - case PV_OFU: return (char_u *)&(curbuf->b_p_ofu); - case PV_EOL: return (char_u *)&(curbuf->b_p_eol); - case PV_FIXEOL: return (char_u *)&(curbuf->b_p_fixeol); - case PV_ET: return (char_u *)&(curbuf->b_p_et); - case PV_FENC: return (char_u *)&(curbuf->b_p_fenc); - case PV_FF: return (char_u *)&(curbuf->b_p_ff); - case PV_FT: return (char_u *)&(curbuf->b_p_ft); - case PV_FO: return (char_u *)&(curbuf->b_p_fo); - case PV_FLP: return (char_u *)&(curbuf->b_p_flp); - case PV_IMI: return (char_u *)&(curbuf->b_p_iminsert); - case PV_IMS: return (char_u *)&(curbuf->b_p_imsearch); - case PV_INF: return (char_u *)&(curbuf->b_p_inf); - case PV_ISK: return (char_u *)&(curbuf->b_p_isk); - case PV_INEX: return (char_u *)&(curbuf->b_p_inex); - case PV_INDE: return (char_u *)&(curbuf->b_p_inde); - case PV_INDK: return (char_u *)&(curbuf->b_p_indk); - case PV_FEX: return (char_u *)&(curbuf->b_p_fex); - case PV_LISP: return (char_u *)&(curbuf->b_p_lisp); - case PV_ML: return (char_u *)&(curbuf->b_p_ml); - case PV_MPS: return (char_u *)&(curbuf->b_p_mps); - case PV_MA: return (char_u *)&(curbuf->b_p_ma); - case PV_MOD: return (char_u *)&(curbuf->b_changed); - case PV_NF: return (char_u *)&(curbuf->b_p_nf); - case PV_PI: return (char_u *)&(curbuf->b_p_pi); - case PV_QE: return (char_u *)&(curbuf->b_p_qe); - case PV_RO: return (char_u *)&(curbuf->b_p_ro); - case PV_SCBK: return (char_u *)&(curbuf->b_p_scbk); - case PV_SI: return (char_u *)&(curbuf->b_p_si); - case PV_STS: return (char_u *)&(curbuf->b_p_sts); - case PV_SUA: return (char_u *)&(curbuf->b_p_sua); - case PV_SWF: return (char_u *)&(curbuf->b_p_swf); - case PV_SMC: return (char_u *)&(curbuf->b_p_smc); - case PV_SYN: return (char_u *)&(curbuf->b_p_syn); - case PV_SPC: return (char_u *)&(curwin->w_s->b_p_spc); - case PV_SPF: return (char_u *)&(curwin->w_s->b_p_spf); - case PV_SPL: return (char_u *)&(curwin->w_s->b_p_spl); - case PV_SPO: return (char_u *)&(curwin->w_s->b_p_spo); - case PV_SW: return (char_u *)&(curbuf->b_p_sw); - case PV_TFU: return (char_u *)&(curbuf->b_p_tfu); - case PV_TS: return (char_u *)&(curbuf->b_p_ts); - case PV_TW: return (char_u *)&(curbuf->b_p_tw); - case PV_UDF: return (char_u *)&(curbuf->b_p_udf); - case PV_WM: return (char_u *)&(curbuf->b_p_wm); - case PV_VSTS: return (char_u *)&(curbuf->b_p_vsts); - case PV_VTS: return (char_u *)&(curbuf->b_p_vts); - case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap); - case PV_SCL: return (char_u *)&(curwin->w_p_scl); - case PV_WINHL: return (char_u *)&(curwin->w_p_winhl); - case PV_WINBL: return (char_u *)&(curwin->w_p_winbl); - default: IEMSG(_("E356: get_varp ERROR")); + case PV_CFU: + return (char_u *)&(curbuf->b_p_cfu); + case PV_OFU: + return (char_u *)&(curbuf->b_p_ofu); + case PV_EOL: + return (char_u *)&(curbuf->b_p_eol); + case PV_FIXEOL: + return (char_u *)&(curbuf->b_p_fixeol); + case PV_ET: + return (char_u *)&(curbuf->b_p_et); + case PV_FENC: + return (char_u *)&(curbuf->b_p_fenc); + case PV_FF: + return (char_u *)&(curbuf->b_p_ff); + case PV_FT: + return (char_u *)&(curbuf->b_p_ft); + case PV_FO: + return (char_u *)&(curbuf->b_p_fo); + case PV_FLP: + return (char_u *)&(curbuf->b_p_flp); + case PV_IMI: + return (char_u *)&(curbuf->b_p_iminsert); + case PV_IMS: + return (char_u *)&(curbuf->b_p_imsearch); + case PV_INF: + return (char_u *)&(curbuf->b_p_inf); + case PV_ISK: + return (char_u *)&(curbuf->b_p_isk); + case PV_INEX: + return (char_u *)&(curbuf->b_p_inex); + case PV_INDE: + return (char_u *)&(curbuf->b_p_inde); + case PV_INDK: + return (char_u *)&(curbuf->b_p_indk); + case PV_FEX: + return (char_u *)&(curbuf->b_p_fex); + case PV_LISP: + return (char_u *)&(curbuf->b_p_lisp); + case PV_ML: + return (char_u *)&(curbuf->b_p_ml); + case PV_MPS: + return (char_u *)&(curbuf->b_p_mps); + case PV_MA: + return (char_u *)&(curbuf->b_p_ma); + case PV_MOD: + return (char_u *)&(curbuf->b_changed); + case PV_NF: + return (char_u *)&(curbuf->b_p_nf); + case PV_PI: + return (char_u *)&(curbuf->b_p_pi); + case PV_QE: + return (char_u *)&(curbuf->b_p_qe); + case PV_RO: + return (char_u *)&(curbuf->b_p_ro); + case PV_SCBK: + return (char_u *)&(curbuf->b_p_scbk); + case PV_SI: + return (char_u *)&(curbuf->b_p_si); + case PV_STS: + return (char_u *)&(curbuf->b_p_sts); + case PV_SUA: + return (char_u *)&(curbuf->b_p_sua); + case PV_SWF: + return (char_u *)&(curbuf->b_p_swf); + case PV_SMC: + return (char_u *)&(curbuf->b_p_smc); + case PV_SYN: + return (char_u *)&(curbuf->b_p_syn); + case PV_SPC: + return (char_u *)&(curwin->w_s->b_p_spc); + case PV_SPF: + return (char_u *)&(curwin->w_s->b_p_spf); + case PV_SPL: + return (char_u *)&(curwin->w_s->b_p_spl); + case PV_SPO: + return (char_u *)&(curwin->w_s->b_p_spo); + case PV_SW: + return (char_u *)&(curbuf->b_p_sw); + case PV_TFU: + return (char_u *)&(curbuf->b_p_tfu); + case PV_TS: + return (char_u *)&(curbuf->b_p_ts); + case PV_TW: + return (char_u *)&(curbuf->b_p_tw); + case PV_UDF: + return (char_u *)&(curbuf->b_p_udf); + case PV_WM: + return (char_u *)&(curbuf->b_p_wm); + case PV_VSTS: + return (char_u *)&(curbuf->b_p_vsts); + case PV_VTS: + return (char_u *)&(curbuf->b_p_vts); + case PV_KMAP: + return (char_u *)&(curbuf->b_p_keymap); + case PV_SCL: + return (char_u *)&(curwin->w_p_scl); + case PV_WINHL: + return (char_u *)&(curwin->w_p_winhl); + case PV_WINBL: + return (char_u *)&(curwin->w_p_winbl); + default: + IEMSG(_("E356: get_varp ERROR")); } // always return a valid pointer to avoid a crash! return (char_u *)&(curbuf->b_p_wm); @@ -5963,7 +6094,7 @@ void didset_window_options(win_T *wp) void buf_copy_options(buf_T *buf, int flags) { int should_copy = true; - char_u *save_p_isk = NULL; // init for GCC + char_u *save_p_isk = NULL; // init for GCC int dont_do_help; int did_isk = false; @@ -6008,22 +6139,18 @@ void buf_copy_options(buf_T *buf, int flags) buf->b_p_ro = false; // don't copy readonly buf->b_p_fenc = vim_strsave(p_fenc); switch (*p_ffs) { - case 'm': { - buf->b_p_ff = vim_strsave((char_u *)FF_MAC); - break; - } - case 'd': { - buf->b_p_ff = vim_strsave((char_u *)FF_DOS); - break; - } - case 'u': { - buf->b_p_ff = vim_strsave((char_u *)FF_UNIX); - break; - } - default: { - buf->b_p_ff = vim_strsave(p_ff); - break; - } + case 'm': + buf->b_p_ff = vim_strsave((char_u *)FF_MAC); + break; + case 'd': + buf->b_p_ff = vim_strsave((char_u *)FF_DOS); + break; + case 'u': + buf->b_p_ff = vim_strsave((char_u *)FF_UNIX); + break; + default: + buf->b_p_ff = vim_strsave(p_ff); + break; } buf->b_p_bh = empty_option; buf->b_p_bt = empty_option; @@ -6204,21 +6331,17 @@ void set_imsearch_global(void) } static int expand_option_idx = -1; -static char_u expand_option_name[5] = {'t', '_', NUL, NUL, NUL}; +static char_u expand_option_name[5] = { 't', '_', NUL, NUL, NUL }; static int expand_option_flags = 0; -void -set_context_in_set_cmd( - expand_T *xp, - char_u *arg, - int opt_flags // OPT_GLOBAL and/or OPT_LOCAL -) +/// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL +void set_context_in_set_cmd(expand_T *xp, char_u *arg, int opt_flags) { char_u nextchar; uint32_t flags = 0; // init for GCC int opt_idx = 0; // init for GCC - char_u *p; - char_u *s; + char_u *p; + char_u *s; int is_term_option = false; int key; @@ -6342,15 +6465,14 @@ set_context_in_set_cmd( || p == (char_u *)&p_pp || p == (char_u *)&p_rtp || p == (char_u *)&p_cdpath - || p == (char_u *)&p_vdir - ) { + || p == (char_u *)&p_vdir) { xp->xp_context = EXPAND_DIRECTORIES; if (p == (char_u *)&p_path - || p == (char_u *)&p_cdpath - ) + || p == (char_u *)&p_cdpath) { xp->xp_backslash = XP_BS_THREE; - else + } else { xp->xp_backslash = XP_BS_ONE; + } } else if (p == (char_u *)&p_ft) { xp->xp_context = EXPAND_FILETYPE; } else { @@ -6396,7 +6518,7 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u *** int num_normal = 0; // Nr of matching non-term-code settings int match; int count = 0; - char_u *str; + char_u *str; int loop; static char *(names[]) = { "all" }; int ic = regmatch->rm_ic; // remember the ignore-case flag @@ -6440,8 +6562,9 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u *** if (match) { if (loop == 0) { num_normal++; - } else + } else { (*file)[count++] = vim_strsave(str); + } } } @@ -6503,13 +6626,11 @@ void ExpandOldSetting(int *num_file, char_u ***file) /// Get the value for the numeric or string option///opp in a nice format into /// NameBuff[]. Must not be called with a hidden option! -static void -option_value2string( - vimoption_T *opp, - int opt_flags // OPT_GLOBAL and/or OPT_LOCAL -) +/// +/// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL +static void option_value2string(vimoption_T *opp, int opt_flags) { - char_u *varp; + char_u *varp; varp = get_varp_scope(opp, opt_flags); @@ -6532,7 +6653,7 @@ option_value2string( NameBuff[0] = NUL; } else if (opp->flags & P_EXPAND) { home_replace(NULL, varp, NameBuff, MAXPATHL, false); - // Translate 'pastetoggle' into special key names. + // Translate 'pastetoggle' into special key names. } else if ((char_u **)opp->var == &p_pt) { str2specialbuf((const char *)p_pt, (char *)NameBuff, MAXPATHL); } else { @@ -6645,8 +6766,8 @@ static void langmap_init(void) /// changed at any time! static void langmap_set(void) { - char_u *p; - char_u *p2; + char_u *p; + char_u *p2; int from, to; ga_clear(&langmap_mapga); // clear the previous map first @@ -6692,7 +6813,7 @@ static void langmap_set(void) } if (to == NUL) { EMSG2(_("E357: 'langmap': Matching character missing for %s"), - transchar(from)); + transchar(from)); return; } @@ -6711,9 +6832,8 @@ static void langmap_set(void) p = p2; if (p[0] != NUL) { if (p[0] != ',') { - EMSG2(_( - "E358: 'langmap': Extra characters after semicolon: %s"), - p); + EMSG2(_("E358: 'langmap': Extra characters after semicolon: %s"), + p); return; } p++; @@ -6938,7 +7058,7 @@ void reset_option_was_set(const char *name) /// fill_breakat_flags() -- called when 'breakat' changes value. static void fill_breakat_flags(void) { - char_u *p; + char_u *p; int i; for (i = 0; i < 256; i++) { @@ -6997,13 +7117,10 @@ static int fill_culopt_flags(char_u *val, win_T *wp) /// Check an option that can be a range of string values. /// -/// Return OK for correct value, FAIL otherwise. -/// Empty is always OK. -static int check_opt_strings( - char_u *val, - char **values, - int list // when true: accept a list of values -) +/// @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) { return opt_strings_flags(val, values, NULL, list); } @@ -7011,14 +7128,12 @@ static int check_opt_strings( /// Handle an option that can be a range of string values. /// Set a flag in "*flagp" for each string present. /// -/// Return OK for correct value, FAIL otherwise. -/// Empty is always OK. -static int opt_strings_flags( - char_u *val, // new value - char **values, // array of valid string values - unsigned *flagp, - bool list // when true: accept a list of values -) +/// @param val new value +/// @param values array of valid string values +/// @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) { unsigned int new_flags = 0; @@ -7049,7 +7164,7 @@ static int opt_strings_flags( static int check_opt_wim(void) { char_u new_wim_flags[4]; - char_u *p; + char_u *p; int i; int idx = 0; @@ -7106,10 +7221,14 @@ bool can_bs(int what) return false; } switch (*p_bs) { - case '3': return true; - case '2': return what != BS_NOSTOP; - case '1': return what != BS_START; - case '0': return false; + case '3': + return true; + case '2': + return what != BS_NOSTOP; + case '1': + return what != BS_START; + case '0': + return false; } return vim_strchr(p_bs, what) != NULL; } @@ -7306,11 +7425,7 @@ colnr_T tabstop_start(colnr_T col, long ts, long *vts) // Find the number of tabs and spaces necessary to get from one column // to another. -void tabstop_fromto(colnr_T start_col, - colnr_T end_col, - long ts_arg, - long *vts, - int *ntabs, +void tabstop_fromto(colnr_T start_col, colnr_T end_col, long ts_arg, long *vts, int *ntabs, int *nspcs) { int spaces = end_col - start_col; @@ -7486,18 +7601,13 @@ static bool briopt_check(win_T *wp) while (*p != NUL) { if (STRNCMP(p, "shift:", 6) == 0 - && ((p[6] == '-' && ascii_isdigit(p[7])) || ascii_isdigit(p[6]))) - { + && ((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])) - { + } 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) - { + } else if (STRNCMP(p, "sbr", 3) == 0) { p += 3; bri_sbr = true; } else if (STRNCMP(p, "list:", 5) == 0) { @@ -7590,8 +7700,10 @@ int get_fileformat_force(const buf_T *buf, const exarg_T *eap) int default_fileformat(void) { switch (*p_ffs) { - case 'm': return EOL_MAC; - case 'd': return EOL_DOS; + case 'm': + return EOL_MAC; + case 'd': + return EOL_DOS; } return EOL_UNIX; } @@ -7607,15 +7719,15 @@ void set_fileformat(int eol_style, int opt_flags) char *p = NULL; switch (eol_style) { - case EOL_UNIX: - p = FF_UNIX; - break; - case EOL_MAC: - p = FF_MAC; - break; - case EOL_DOS: - p = FF_DOS; - break; + case EOL_UNIX: + p = FF_UNIX; + break; + case EOL_MAC: + p = FF_MAC; + break; + case EOL_DOS: + p = FF_DOS; + break; } // p is NULL if "eol_style" is EOL_UNKNOWN. @@ -7653,11 +7765,10 @@ char_u *skip_to_option_part(const char_u *p) /// @param[in] sep_chars chars that separate the option parts /// /// @return length of `*option` -size_t copy_option_part(char_u **option, char_u *buf, size_t maxlen, - char *sep_chars) +size_t copy_option_part(char_u **option, char_u *buf, size_t maxlen, char *sep_chars) { size_t len = 0; - char_u *p = *option; + char_u *p = *option; // skip '.' at start of option part, for 'suffixes' if (*p == '.') { @@ -7820,52 +7931,52 @@ Dictionary get_all_vimoptions(void) static Dictionary vimoption2dict(vimoption_T *opt) { - Dictionary dict = ARRAY_DICT_INIT; + Dictionary dict = ARRAY_DICT_INIT; - PUT(dict, "name", CSTR_TO_OBJ(opt->fullname)); - PUT(dict, "shortname", CSTR_TO_OBJ(opt->shortname)); + PUT(dict, "name", CSTR_TO_OBJ(opt->fullname)); + PUT(dict, "shortname", CSTR_TO_OBJ(opt->shortname)); - const char *scope; - if (opt->indir & PV_BUF) { - scope = "buf"; - } else if (opt->indir & PV_WIN) { - scope = "win"; - } else { - scope = "global"; - } - - PUT(dict, "scope", CSTR_TO_OBJ(scope)); - - // welcome to the jungle - PUT(dict, "global_local", BOOL(opt->indir & PV_BOTH)); - PUT(dict, "commalist", BOOL(opt->flags & P_COMMA)); - PUT(dict, "flaglist", BOOL(opt->flags & P_FLAGLIST)); - - PUT(dict, "was_set", BOOL(opt->flags & P_WAS_SET)); - - PUT(dict, "last_set_sid", INTEGER_OBJ(opt->last_set.script_ctx.sc_sid)); - PUT(dict, "last_set_linenr", INTEGER_OBJ(opt->last_set.script_ctx.sc_lnum)); - PUT(dict, "last_set_chan", INTEGER_OBJ((int64_t)opt->last_set.channel_id)); - - const char *type; - Object def; - // TODO(bfredl): do you even nocp? - char_u *def_val = opt->def_val; - if (opt->flags & P_STRING) { - type = "string"; - def = CSTR_TO_OBJ(def_val ? (char *)def_val : ""); - } else if (opt->flags & P_NUM) { - type = "number"; - def = INTEGER_OBJ((Integer)(intptr_t)def_val); - } else if (opt->flags & P_BOOL) { - type = "boolean"; - def = BOOL((intptr_t)def_val); - } else { - type = ""; def = NIL; - } - PUT(dict, "type", CSTR_TO_OBJ(type)); - PUT(dict, "default", def); - PUT(dict, "allows_duplicates", BOOL(!(opt->flags & P_NODUP))); + const char *scope; + if (opt->indir & PV_BUF) { + scope = "buf"; + } else if (opt->indir & PV_WIN) { + scope = "win"; + } else { + scope = "global"; + } + + PUT(dict, "scope", CSTR_TO_OBJ(scope)); + + // welcome to the jungle + PUT(dict, "global_local", BOOL(opt->indir & PV_BOTH)); + PUT(dict, "commalist", BOOL(opt->flags & P_COMMA)); + PUT(dict, "flaglist", BOOL(opt->flags & P_FLAGLIST)); + + PUT(dict, "was_set", BOOL(opt->flags & P_WAS_SET)); + + PUT(dict, "last_set_sid", INTEGER_OBJ(opt->last_set.script_ctx.sc_sid)); + PUT(dict, "last_set_linenr", INTEGER_OBJ(opt->last_set.script_ctx.sc_lnum)); + PUT(dict, "last_set_chan", INTEGER_OBJ((int64_t)opt->last_set.channel_id)); + + const char *type; + Object def; + // TODO(bfredl): do you even nocp? + char_u *def_val = opt->def_val; + if (opt->flags & P_STRING) { + type = "string"; + def = CSTR_TO_OBJ(def_val ? (char *)def_val : ""); + } else if (opt->flags & P_NUM) { + type = "number"; + def = INTEGER_OBJ((Integer)(intptr_t)def_val); + } else if (opt->flags & P_BOOL) { + type = "boolean"; + def = BOOL((intptr_t)def_val); + } else { + type = ""; def = NIL; + } + PUT(dict, "type", CSTR_TO_OBJ(type)); + PUT(dict, "default", def); + PUT(dict, "allows_duplicates", BOOL(!(opt->flags & P_NODUP))); - return dict; + return dict; } diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index f0d446b4c5..2bff65b241 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -873,10 +873,10 @@ static void system_data_cb(Stream *stream, RBuffer *buf, size_t count, void *dat /// Returns the previous decision if size=0. static bool out_data_decide_throttle(size_t size) { - static uint64_t started = 0; // Start time of the current throttle. - static size_t received = 0; // Bytes observed since last throttle. - static size_t visit = 0; // "Pulse" count of the current throttle. - static char pulse_msg[] = { ' ', ' ', ' ', '\0' }; + static uint64_t started = 0; // Start time of the current throttle. + static size_t received = 0; // Bytes observed since last throttle. + static size_t visit = 0; // "Pulse" count of the current throttle. + static char pulse_msg[] = { ' ', ' ', ' ', '\0' }; if (!size) { bool previous_decision = (visit > 0); @@ -933,8 +933,8 @@ static bool out_data_decide_throttle(size_t size) static void out_data_ring(char *output, size_t size) { #define MAX_CHUNK_SIZE (OUT_DATA_THRESHOLD / 2) - static char last_skipped[MAX_CHUNK_SIZE]; // Saved output. - static size_t last_skipped_len = 0; + static char last_skipped[MAX_CHUNK_SIZE]; // Saved output. + static size_t last_skipped_len = 0; assert(output != NULL || (size == 0 || size == SIZE_MAX)); diff --git a/src/nvim/os/tty.c b/src/nvim/os/tty.c index c80ef99084..126b1b0044 100644 --- a/src/nvim/os/tty.c +++ b/src/nvim/os/tty.c @@ -23,15 +23,6 @@ /// @param out_fd stdout file descriptor void os_tty_guess_term(const char **term, int out_fd) { - bool winpty = (os_getenv("NVIM") != NULL); - - if (winpty) { - // Force TERM=win32con when running in winpty. - *term = "win32con"; - uv_tty_set_vterm_state(UV_TTY_UNSUPPORTED); - return; - } - bool conemu_ansi = strequal(os_getenv("ConEmuANSI"), "ON"); bool vtp = false; diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 44274e8f1d..9396a5896a 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -7,14 +7,13 @@ #include <stdbool.h> #include <string.h> -#include "nvim/vim.h" #include "nvim/ascii.h" -#include "nvim/os_unix.h" #include "nvim/buffer.h" #include "nvim/charset.h" #include "nvim/eval.h" #include "nvim/ex_cmds.h" #include "nvim/fileio.h" +#include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/main.h" #include "nvim/mbyte.h" @@ -23,19 +22,20 @@ #include "nvim/message.h" #include "nvim/misc1.h" #include "nvim/mouse.h" -#include "nvim/garray.h" +#include "nvim/msgpack_rpc/helpers.h" +#include "nvim/os/input.h" +#include "nvim/os/os.h" +#include "nvim/os/shell.h" +#include "nvim/os/signal.h" +#include "nvim/os/time.h" +#include "nvim/os_unix.h" #include "nvim/path.h" #include "nvim/screen.h" #include "nvim/strings.h" #include "nvim/syntax.h" -#include "nvim/ui.h" #include "nvim/types.h" -#include "nvim/os/os.h" -#include "nvim/os/time.h" -#include "nvim/os/input.h" -#include "nvim/os/shell.h" -#include "nvim/os/signal.h" -#include "nvim/msgpack_rpc/helpers.h" +#include "nvim/ui.h" +#include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os_unix.c.generated.h" @@ -61,13 +61,15 @@ vim_acl_T mch_get_acl(const char_u *fname) // Set the ACL of file "fname" to "acl" (unless it's NULL). void mch_set_acl(const char_u *fname, vim_acl_T aclent) { - if (aclent == NULL) + if (aclent == NULL) { return; + } } void mch_free_acl(vim_acl_T aclent) { - if (aclent == NULL) + if (aclent == NULL) { return; + } } #endif diff --git a/src/nvim/path.c b/src/nvim/path.c index 5d14eba0a5..60c7ea7fa4 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -6,15 +6,13 @@ #include <stdbool.h> #include <stdlib.h> -#include "nvim/vim.h" #include "nvim/ascii.h" -#include "nvim/path.h" #include "nvim/charset.h" #include "nvim/eval.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" -#include "nvim/fileio.h" #include "nvim/file_search.h" +#include "nvim/fileio.h" #include "nvim/garray.h" #include "nvim/memfile.h" #include "nvim/memline.h" @@ -22,20 +20,22 @@ #include "nvim/message.h" #include "nvim/misc1.h" #include "nvim/option.h" +#include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/shell.h" #include "nvim/os_unix.h" +#include "nvim/path.h" #include "nvim/quickfix.h" #include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/strings.h" #include "nvim/tag.h" #include "nvim/types.h" -#include "nvim/os/input.h" +#include "nvim/vim.h" #include "nvim/window.h" -#define URL_SLASH 1 /* path_is_url() has found "://" */ -#define URL_BACKSLASH 2 /* 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 # undef gen_expand_wildcards @@ -53,8 +53,8 @@ /// @param checkname When both files don't exist, only compare their names. /// @param expandenv Whether to expand environment variables in file names. /// @return Enum of type FileComparison. @see FileComparison. -FileComparison path_full_compare(char_u *const s1, char_u *const s2, - const bool checkname, const bool expandenv) +FileComparison path_full_compare(char_u *const s1, char_u *const s2, const bool checkname, + const bool expandenv) { assert(s1 && s2); char_u exp1[MAXPATHL]; @@ -63,9 +63,9 @@ FileComparison path_full_compare(char_u *const s1, char_u *const s2, FileID file_id_1, file_id_2; if (expandenv) { - expand_env(s1, exp1, MAXPATHL); + expand_env(s1, exp1, MAXPATHL); } else { - xstrlcpy((char *)exp1, (const char *)s1, MAXPATHL); + xstrlcpy((char *)exp1, (const char *)s1, MAXPATHL); } bool id_ok_1 = os_fileid((char *)exp1, &file_id_1); bool id_ok_2 = os_fileid((char *)s2, &file_id_2); @@ -146,7 +146,7 @@ char_u *path_tail_with_sep(char_u *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 = get_past_head((char_u *)invocation); const char_u *p = tail; while (*p != NUL && *p != ' ') { bool was_sep = vim_ispathsep_nocolon(*p); @@ -266,7 +266,7 @@ int vim_ispathlistsep(int c) #ifdef UNIX return c == ':'; #else - return c == ';'; /* might not be right for every system... */ + return c == ';'; // might not be right for every system... #endif } @@ -280,11 +280,12 @@ char_u *shorten_dir(char_u *str) char_u *d = str; bool skip = false; for (char_u *s = str;; ++s) { - if (s >= tail) { /* copy the whole tail */ + if (s >= tail) { // copy the whole tail *d++ = *s; - if (*s == NUL) + if (*s == NUL) { break; - } else if (vim_ispathsep(*s)) { /* copy '/' and next char */ + } + } else if (vim_ispathsep(*s)) { // copy '/' and next char *d++ = *s; skip = false; } else if (!skip) { @@ -348,8 +349,7 @@ int path_fnamecmp(const char *fname1, const char *fname2) /// @param[in] len Compare at most len bytes. /// /// @return 0 if they are equal, non-zero otherwise. -int path_fnamencmp(const char *const fname1, const char *const fname2, - size_t len) +int path_fnamencmp(const char *const fname1, const char *const fname2, size_t len) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { #ifdef BACKSLASH_IN_FILENAME @@ -389,9 +389,8 @@ int path_fnamencmp(const char *const fname1, const char *const fname2, /// add a path separator before fname2. /// /// @return fname1 -static inline char *do_concat_fnames(char *fname1, const size_t len1, - const char *fname2, const size_t len2, - const bool sep) +static inline char *do_concat_fnames(char *fname1, const size_t len1, const char *fname2, + const size_t len2, const bool sep) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { if (sep && *fname1 && !after_pathsep(fname1, fname1 + len1)) { @@ -548,7 +547,7 @@ bool path_has_exp_wildcard(const char_u *p) #else const char *wildcards = "*?["; // Windows. #endif - if (vim_strchr((char_u *) wildcards, *p) != NULL) { + if (vim_strchr((char_u *)wildcards, *p) != NULL) { return true; } } @@ -590,8 +589,8 @@ 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, bool didstar) +static size_t do_path_expand(garray_T *gap, const char_u *path, size_t wildoff, int flags, + bool didstar) FUNC_ATTR_NONNULL_ALL { int start_len = gap->ga_len; @@ -599,11 +598,12 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, bool starstar = false; static int stardepth = 0; // depth for "**" expansion - /* Expanding "**" may take a long time, check for CTRL-C. */ + // Expanding "**" may take a long time, check for CTRL-C. if (stardepth > 0) { os_breakcheck(); - if (got_int) + if (got_int) { return 0; + } } // Make room for file name. When doing encoding conversion the actual @@ -633,7 +633,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, || (!p_fic && (flags & EW_ICASE) && isalpha(PTR2CHAR(path_end))) #endif - )) { + )) { e = p; } len = (size_t)(utfc_ptr2len(path_end)); @@ -644,20 +644,23 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, e = p; *e = NUL; - /* Now we have one wildcard component between "s" and "e". */ + // 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) + for (p = buf + wildoff; p < s; ++p) { if (rem_backslash(p)) { STRMOVE(p, p + 1); --e; --s; } + } - /* Check for "**" between "s" and "e". */ - for (p = s; p < e; ++p) - if (p[0] == '*' && p[1] == '*') + // Check for "**" between "s" and "e". + for (p = s; p < e; ++p) { + if (p[0] == '*' && p[1] == '*') { starstar = true; + } + } // convert the file pattern to a regexp pattern int starts_with_dot = *s == '.'; @@ -675,11 +678,13 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, #else regmatch.rm_ic = true; // Always ignore case on Windows. #endif - if (flags & (EW_NOERROR | EW_NOTWILD)) + if (flags & (EW_NOERROR | EW_NOTWILD)) { ++emsg_silent; + } regmatch.regprog = vim_regcomp(pat, RE_MAGIC); - if (flags & (EW_NOERROR | EW_NOTWILD)) + if (flags & (EW_NOERROR | EW_NOTWILD)) { --emsg_silent; + } xfree(pat); if (regmatch.regprog == NULL && (flags & EW_NOTWILD) == 0) { @@ -727,9 +732,9 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, } STRCPY(buf + len, path_end); - 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 */ + 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); } else { FileInfo file_info; @@ -741,7 +746,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, } // add existing file or symbolic link if ((flags & EW_ALLLINKS) ? os_fileinfo_link((char *)buf, &file_info) - : os_path_exists(buf)) { + : os_path_exists(buf)) { addfile(gap, buf, flags); } } @@ -767,14 +772,16 @@ static size_t do_path_expand(garray_T *gap, const char_u *path, */ static int find_previous_pathsep(char_u *path, char_u **psep) { - /* skip the current separator */ - if (*psep > path && vim_ispathsep(**psep)) + // skip the current separator + if (*psep > path && vim_ispathsep(**psep)) { --*psep; + } - /* find the previous separator */ + // find the previous separator while (*psep > path) { - if (vim_ispathsep(**psep)) + if (vim_ispathsep(**psep)) { return OK; + } MB_PTR_BACK(path, *psep); } @@ -828,8 +835,9 @@ static void expand_path_option(char_u *curdir, garray_T *gap) /* Relative to current buffer: * "/path/file" + "." -> "/path/" * "/path/file" + "./subdir" -> "/path/subdir" */ - if (curbuf->b_ffname == NULL) + if (curbuf->b_ffname == NULL) { continue; + } char_u *p = path_tail(curbuf->b_ffname); size_t len = (size_t)(p - curbuf->b_ffname); if (len + STRLEN(buf) >= MAXPATHL) { @@ -870,13 +878,13 @@ static void expand_path_option(char_u *curdir, garray_T *gap) * * path: /foo/bar/baz * fname: /foo/bar/baz/quux.txt - * returns: ^this + * returns: ^this */ static char_u *get_path_cutoff(char_u *fname, garray_T *gap) { int maxlen = 0; - char_u **path_part = (char_u **)gap->ga_data; - char_u *cutoff = NULL; + char_u **path_part = (char_u **)gap->ga_data; + char_u *cutoff = NULL; for (int i = 0; i < gap->ga_len; i++) { int j = 0; @@ -932,14 +940,16 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) STRCAT(file_pattern, pattern); char_u *pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, true); xfree(file_pattern); - if (pat == NULL) + if (pat == NULL) { return; + } - regmatch.rm_ic = TRUE; /* always ignore case */ + regmatch.rm_ic = TRUE; // always ignore case regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); xfree(pat); - if (regmatch.regprog == NULL) + if (regmatch.regprog == NULL) { return; + } char_u *curdir = xmalloc(MAXPATHL); os_dirname(curdir, MAXPATHL); @@ -951,16 +961,17 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) char_u *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_u *pathsep_p; + char_u *path_cutoff; len = STRLEN(path); is_in_curdir = fnamencmp(curdir, path, dir_end - path) == 0 && curdir[dir_end - path] == NUL; - if (is_in_curdir) + if (is_in_curdir) { in_curdir[i] = vim_strsave(path); + } - /* Shorten the filename while maintaining its uniqueness */ + // Shorten the filename while maintaining its uniqueness path_cutoff = get_path_cutoff(path, &path_ga); // Don't assume all files can be reached without path when search @@ -1010,19 +1021,21 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) os_breakcheck(); } - /* Shorten filenames in /in/current/directory/{filename} */ + // 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]; - if (path == NULL) + if (path == NULL) { continue; + } /* 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) + if (short_name == NULL) { short_name = path; + } if (is_unique(short_name, gap, i)) { STRCPY(fnames[i], short_name); continue; @@ -1040,14 +1053,16 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) } xfree(curdir); - for (int i = 0; i < gap->ga_len; i++) + for (int i = 0; i < gap->ga_len; i++) { xfree(in_curdir[i]); + } xfree(in_curdir); ga_clear_strings(&path_ga); vim_regfree(regmatch.regprog); - if (sort_again) + if (sort_again) { ga_remove_duplicate_strings(gap); + } } /// Find end of the directory name @@ -1072,8 +1087,9 @@ const char *gettail_dir(const char *const fname) look_for_sep = false; } } else { - if (!look_for_sep) + if (!look_for_sep) { dir_end = next_dir_end; + } look_for_sep = true; } MB_PTR_ADV(p); @@ -1082,16 +1098,12 @@ const char *gettail_dir(const char *const fname) } -/* - * Calls globpath() with 'path' values for the given pattern and stores the - * result in "gap". - * Returns the total number of matches. - */ -static int expand_in_path( - garray_T *const gap, - char_u *const pattern, - const int flags // EW_* flags -) +/// Calls globpath() with 'path' values for the given pattern and stores the +/// result in "gap". +/// Returns the total number of matches. +/// +/// @param flags EW_* flags +static int expand_in_path(garray_T *const gap, char_u *const pattern, const int flags) { garray_T path_ga; @@ -1131,7 +1143,7 @@ static bool has_env_var(char_u *p) for (; *p; MB_PTR_ADV(p)) { if (*p == '\\' && p[1] != NUL) { p++; - } else if (vim_strchr((char_u *) "$" , *p) != NULL) { + } else if (vim_strchr((char_u *)"$", *p) != NULL) { return true; } } @@ -1186,8 +1198,7 @@ static bool has_special_wildchar(char_u *p) /// 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 gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, - char_u ***file, int flags) +int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file, int flags) { garray_T ga; char_u *p; @@ -1203,9 +1214,9 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, */ 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 @@ -1247,8 +1258,9 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, // First expand environment variables, "~/" and "~user/". if ((has_env_var(p) && !(flags & EW_NOTENV)) || *p == '~') { p = expand_env_save_opt(p, true); - if (p == NULL) + if (p == NULL) { p = pat[i]; + } #ifdef UNIX /* * On Unix, if expand_env() can't expand an environment @@ -1278,8 +1290,8 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, && !path_is_absolute(p) && !(p[0] == '.' && (vim_ispathsep(p[1]) - || (p[1] == '.' && vim_ispathsep(p[2])))) - ) { + || (p[1] == '.' && + vim_ispathsep(p[2]))))) { /* :find completion where 'path' is used. * Recursiveness is OK here. */ recursive = false; @@ -1295,7 +1307,7 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, } if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND))) { - char_u *t = backslash_halve_save(p); + char_u *t = backslash_halve_save(p); /* When EW_NOTFOUND is used, always add files and dirs. Makes * "vim c:/" work. */ @@ -1310,10 +1322,12 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, } } - if (did_expand_in_path && !GA_EMPTY(&ga) && (flags & EW_PATH)) + if (did_expand_in_path && !GA_EMPTY(&ga) && (flags & EW_PATH)) { uniquefy_paths(&ga, p); - if (p != pat[i]) + } + if (p != pat[i]) { xfree(p); + } } *num_file = ga.ga_len; @@ -1333,14 +1347,12 @@ static int vim_backtick(char_u *p) return *p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`'; } -// Expand an item in `backticks` by executing it as a command. -// Currently only works when pat[] starts and ends with a `. -// Returns number of file names found, -1 if an error is encountered. -static int expand_backtick( - garray_T *gap, - char_u *pat, - int flags /* EW_* flags */ -) +/// Expand an item in `backticks` by executing it as a command. +/// Currently only works when pat[] starts and ends with a `. +/// 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) { char_u *p; char_u *buffer; @@ -1361,11 +1373,12 @@ static int expand_backtick( cmd = buffer; while (*cmd != NUL) { - cmd = skipwhite(cmd); /* skip over white space */ + cmd = skipwhite(cmd); // skip over white space p = cmd; - while (*p != NUL && *p != '\r' && *p != '\n') /* skip over entry */ + while (*p != NUL && *p != '\r' && *p != '\n') { // skip over entry ++p; - /* add an entry if it is not empty */ + } + // add an entry if it is not empty if (p > cmd) { char_u i = *p; *p = NUL; @@ -1374,8 +1387,9 @@ static int expand_backtick( ++cnt; } cmd = p; - while (*cmd != NUL && (*cmd == '\r' || *cmd == '\n')) + while (*cmd != NUL && (*cmd == '\r' || *cmd == '\n')) { ++cmd; + } } xfree(buffer); @@ -1414,18 +1428,16 @@ void slash_adjust(char_u *p) } #endif -// Add a file to a file list. Accepted flags: -// EW_DIR add directories -// EW_FILE add files -// EW_EXEC add executable files -// EW_NOTFOUND add even when it doesn't exist -// EW_ADDSLASH add slash after directory name -// EW_ALLLINKS add symlink also when the referred file does not exist -void addfile( - garray_T *gap, - char_u *f, /* filename */ - int flags -) +/// Add a file to a file list. Accepted flags: +/// EW_DIR add directories +/// EW_FILE add files +/// EW_EXEC add executable files +/// EW_NOTFOUND add even when it doesn't exist +/// EW_ADDSLASH add slash after directory name +/// EW_ALLLINKS add symlink also when the referred file does not exist +/// +/// @param f filename +void addfile(garray_T *gap, char_u *f, int flags) { bool isdir; FileInfo file_info; @@ -1439,14 +1451,16 @@ void addfile( } #ifdef FNAME_ILLEGAL - /* if the file/dir contains illegal characters, don't add it */ - if (vim_strpbrk(f, (char_u *)FNAME_ILLEGAL) != NULL) + // if the file/dir contains illegal characters, don't add it + if (vim_strpbrk(f, (char_u *)FNAME_ILLEGAL) != NULL) { return; + } #endif isdir = os_isdir(f); - if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE))) + if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE))) { return; + } // If the file isn't executable, may not add it. Do accept directories. // When invoked from expand_shellcmd() do not use $PATH. @@ -1464,8 +1478,9 @@ void addfile( /* * Append a slash or backslash after directory names if none is present. */ - if (isdir && (flags & EW_ADDSLASH)) + if (isdir && (flags & EW_ADDSLASH)) { add_pathsep((char *)p); + } GA_APPEND(char_u *, gap, p); } @@ -1478,14 +1493,15 @@ void addfile( void simplify_filename(char_u *filename) { int components = 0; - char_u *p, *tail, *start; + char_u *p, *tail, *start; bool stripping_disabled = false; bool relative = true; p = filename; #ifdef BACKSLASH_IN_FILENAME - if (p[1] == ':') /* skip "x:" */ + if (p[1] == ':') { // skip "x:" p += 2; + } #endif if (vim_ispathsep(*p)) { @@ -1494,17 +1510,18 @@ void simplify_filename(char_u *filename) ++p; while (vim_ispathsep(*p)); } - start = p; /* remember start after "c:/" or "/" or "///" */ + 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. */ - if (vim_ispathsep(*p)) - STRMOVE(p, p + 1); /* remove duplicate "/" */ - else if (p[0] == '.' && (vim_ispathsep(p[1]) || p[1] == NUL)) { - if (p == start && relative) - p += 1 + (p[1] != NUL); /* keep single "." or leading "./" */ - else { + if (vim_ispathsep(*p)) { + STRMOVE(p, p + 1); // remove duplicate "/" + } else if (p[0] == '.' && + (vim_ispathsep(p[1]) || p[1] == NUL)) { + 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 @@ -1527,11 +1544,11 @@ void simplify_filename(char_u *filename) MB_PTR_ADV(tail); } - if (components > 0) { /* strip one preceding component */ + if (components > 0) { // strip one preceding component bool do_strip = false; char_u saved_char; - /* Don't strip for an erroneous file name. */ + // 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 @@ -1613,21 +1630,22 @@ void simplify_filename(char_u *filename) *p++ = '.'; *p = NUL; } else { - if (p > start && tail[-1] == '.') + if (p > start && tail[-1] == '.') { --p; - STRMOVE(p, tail); /* strip previous component */ + } + STRMOVE(p, tail); // strip previous component } --components; } - } else if (p == start && !relative) /* leading "/.." or "/../" */ - STRMOVE(p, tail); /* strip ".." or "../" */ - else { - if (p == start + 2 && p[-2] == '.') { /* leading "./../" */ - STRMOVE(p - 2, p); /* strip leading "./" */ + } else if (p == start && !relative) { // leading "/.." or "/../" + STRMOVE(p, tail); // strip ".." or "../" + } else { + if (p == start + 2 && p[-2] == '.') { // leading "./../" + STRMOVE(p - 2, p); // strip leading "./" tail -= 2; } - p = tail; /* skip to char after ".." or "../" */ + p = tail; // skip to char after ".." or "../" } } else { components++; // Simple path component. @@ -1639,31 +1657,24 @@ 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 = (char *)eval_to_string_safe( - curbuf->b_p_inex, NULL, - was_set_insecurely(curwin, (char_u *)"includeexpr", OPT_LOCAL)); + char *res = (char *)eval_to_string_safe(curbuf->b_p_inex, NULL, + was_set_insecurely(curwin, (char_u *)"includeexpr", + OPT_LOCAL)); set_vim_var_string(VV_FNAME, NULL, 0); return res; } -/* - * Return the name of the file ptr[len] in 'path'. - * Otherwise like file_name_at_cursor(). - */ -char_u * -find_file_name_in_path ( - char_u *ptr, - size_t len, - int options, - long count, - char_u *rel_fname /* file we are searching relative to */ -) +/// Return the name of the file ptr[len] in 'path'. +/// 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_u *file_name; char_u *tofree = NULL; if ((options & FNAME_INCL) && *curbuf->b_p_inex != NUL) { - tofree = (char_u *) eval_includeexpr((char *) ptr, len); + tofree = (char_u *)eval_includeexpr((char *)ptr, len); if (tofree != NULL) { ptr = tofree; len = STRLEN(ptr); @@ -1680,7 +1691,7 @@ find_file_name_in_path ( */ if (file_name == NULL && !(options & FNAME_INCL) && *curbuf->b_p_inex != NUL) { - tofree = (char_u *) eval_includeexpr((char *) ptr, len); + tofree = (char_u *)eval_includeexpr((char *)ptr, len); if (tofree != NULL) { ptr = tofree; len = STRLEN(ptr); @@ -1701,8 +1712,9 @@ find_file_name_in_path ( xfree(file_name); file_name = find_file_in_path(ptr, len, options, FALSE, rel_fname); } - } else + } else { file_name = vim_strnsave(ptr, len); + } xfree(tofree); @@ -1714,10 +1726,11 @@ find_file_name_in_path ( // URL_BACKSLASH. int path_is_url(const char *p) { - if (strncmp(p, "://", 3) == 0) + if (strncmp(p, "://", 3) == 0) { return URL_SLASH; - else if (strncmp(p, ":\\\\", 3) == 0) + } else if (strncmp(p, ":\\\\", 3) == 0) { return URL_BACKSLASH; + } return 0; } @@ -1735,7 +1748,9 @@ int path_with_url(const char *fname) bool path_with_extension(const char *path, const char *extension) { const char *last_dot = strrchr(path, '.'); - if (!last_dot) { return false; } + if (!last_dot) { + return false; + } return strcmp(last_dot + 1, extension) == 0; } @@ -1809,8 +1824,9 @@ char *fix_fname(const char *fname) # ifdef BACKSLASH_IN_FILENAME || strstr(fname, "\\\\") != NULL # endif - ) + ) { return FullName_save(fname, false); + } fname = xstrdup(fname); @@ -1845,7 +1861,7 @@ void path_fix_case(char_u *name) tail = name; } else { *slash = NUL; - ok = os_scandir(&dir, (char *) name); + ok = os_scandir(&dir, (char *)name); *slash = '/'; tail = slash + 1; } @@ -1855,7 +1871,7 @@ void path_fix_case(char_u *name) } char_u *entry; - while ((entry = (char_u *) os_scandir_next(&dir))) { + while ((entry = (char_u *)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)) { @@ -1895,12 +1911,13 @@ int after_pathsep(const char *b, const char *p) bool same_directory(char_u *f1, char_u *f2) { char_u ffname[MAXPATHL]; - char_u *t1; - char_u *t2; + char_u *t1; + char_u *t2; - /* safety check */ - if (f1 == NULL || f2 == NULL) + // safety check + if (f1 == NULL || f2 == NULL) { return false; + } (void)vim_FullName((char *)f1, (char *)ffname, MAXPATHL, FALSE); t1 = path_tail_with_sep(ffname); @@ -1918,22 +1935,23 @@ int pathcmp(const char *p, const char *q, int maxlen) { int i, j; int c1, c2; - const char *s = NULL; + const char *s = NULL; for (i = 0, j = 0; maxlen < 0 || (i < maxlen && j < maxlen);) { c1 = PTR2CHAR((char_u *)p + i); c2 = PTR2CHAR((char_u *)q + j); - /* End of "p": check if "q" also ends or just has a slash. */ + // End of "p": check if "q" also ends or just has a slash. if (c1 == NUL) { - if (c2 == NUL) /* full match */ + if (c2 == NUL) { // full match return 0; + } s = q; i = j; break; } - /* End of "q": check if "p" just has a slash. */ + // End of "q": check if "p" just has a slash. if (c2 == NUL) { s = p; break; @@ -1941,15 +1959,17 @@ int pathcmp(const char *p, const char *q, int maxlen) if ((p_fic ? mb_toupper(c1) != mb_toupper(c2) : c1 != c2) #ifdef BACKSLASH_IN_FILENAME - /* consider '/' and '\\' to be equal */ + // consider '/' and '\\' to be equal && !((c1 == '/' && c2 == '\\') || (c1 == '\\' && c2 == '/')) #endif ) { - if (vim_ispathsep(c1)) + if (vim_ispathsep(c1)) { return -1; - if (vim_ispathsep(c2)) + } + if (vim_ispathsep(c2)) { return 1; + } return p_fic ? mb_toupper(c1) - mb_toupper(c2) : c1 - c2; // no match } @@ -2057,26 +2077,27 @@ 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_u ***file, - int flags) +int expand_wildcards_eval(char_u **pat, int *num_file, char_u ***file, int flags) { int ret = FAIL; - char_u *eval_pat = NULL; - char_u *exp_pat = *pat; - char_u *ignored_msg; + char_u *eval_pat = NULL; + char_u *exp_pat = *pat; + char_u *ignored_msg; size_t usedlen; if (*exp_pat == '%' || *exp_pat == '#' || *exp_pat == '<') { ++emsg_off; eval_pat = eval_vars(exp_pat, exp_pat, &usedlen, - NULL, &ignored_msg, NULL); + NULL, &ignored_msg, NULL); --emsg_off; - if (eval_pat != NULL) + if (eval_pat != NULL) { exp_pat = concat_str(eval_pat, exp_pat + usedlen); + } } - if (exp_pat != NULL) + if (exp_pat != NULL) { ret = expand_wildcards(1, &exp_pat, num_file, file, flags); + } if (eval_pat != NULL) { xfree(exp_pat); @@ -2100,25 +2121,25 @@ int expand_wildcards_eval(char_u **pat, int *num_file, char_u ***file, /// 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(int num_pat, char_u **pat, int *num_files, char_u ***files, - int flags) +int expand_wildcards(int num_pat, char_u **pat, int *num_files, char_u ***files, int flags) { int retval; int i, j; - char_u *p; - int non_suf_match; /* number without matching suffix */ + char_u *p; + int non_suf_match; // number without matching suffix retval = gen_expand_wildcards(num_pat, pat, num_files, files, flags); - /* When keeping all matches, return here */ - if ((flags & EW_KEEPALL) || retval == FAIL) + // When keeping all matches, return here + if ((flags & EW_KEEPALL) || retval == FAIL) { return retval; + } /* * Remove names that match 'wildignore'. */ if (*p_wig) { - char_u *ffname; + char_u *ffname; // check all files in (*files)[] assert(*num_files == 0 || *files != NULL); @@ -2183,7 +2204,7 @@ int match_suffix(char_u *fname) if (setsuflen == 0) { char_u *tail = path_tail(fname); - /* empty entry: match name without a '.' */ + // empty entry: match name without a '.' if (vim_strchr(tail, '.') == NULL) { setsuflen = 1; break; @@ -2209,13 +2230,13 @@ int path_full_dir_name(char *directory, char *buffer, size_t len) int retval = OK; if (STRLEN(directory) == 0) { - return os_dirname((char_u *) buffer, len); + return os_dirname((char_u *)buffer, len); } char old_dir[MAXPATHL]; // Get current directory name. - if (os_dirname((char_u *) old_dir, MAXPATHL) == FAIL) { + if (os_dirname((char_u *)old_dir, MAXPATHL) == FAIL) { return FAIL; } @@ -2229,7 +2250,7 @@ int path_full_dir_name(char *directory, char *buffer, size_t len) retval = FAIL; } - if (retval == FAIL || os_dirname((char_u *) buffer, len) == FAIL) { + if (retval == FAIL || os_dirname((char_u *)buffer, len) == FAIL) { // Do not return immediately since we are in the wrong directory. retval = FAIL; } @@ -2283,14 +2304,13 @@ 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_u *fname, char_u *buf, size_t len, int force) { char_u *p; *buf = NUL; char *relative_directory = xmalloc(len); - char *end_of_path = (char *) fname; + char *end_of_path = (char *)fname; // expand it if forced or not an absolute path if (force || !path_is_absolute(fname)) { @@ -2311,13 +2331,13 @@ static int path_to_absolute(const char_u *fname, char_u *buf, size_t len, memcpy(relative_directory, fname, (size_t)(p - fname)); relative_directory[p-fname] = NUL; } - end_of_path = (char *) (p + 1); + end_of_path = (char *)(p + 1); } else { relative_directory[0] = NUL; - end_of_path = (char *) fname; + end_of_path = (char *)fname; } - if (FAIL == path_full_dir_name(relative_directory, (char *) buf, len)) { + if (FAIL == path_full_dir_name(relative_directory, (char *)buf, len)) { xfree(relative_directory); return FAIL; } diff --git a/src/nvim/plines.c b/src/nvim/plines.c index a656686a95..5b0418ed92 100644 --- a/src/nvim/plines.c +++ b/src/nvim/plines.c @@ -5,18 +5,18 @@ #include <assert.h> #include <inttypes.h> +#include <limits.h> #include <stdbool.h> #include <string.h> -#include <limits.h> -#include "nvim/vim.h" #include "nvim/ascii.h" -#include "nvim/plines.h" +#include "nvim/buffer.h" #include "nvim/charset.h" #include "nvim/cursor.h" +#include "nvim/decoration.h" #include "nvim/diff.h" -#include "nvim/func_attr.h" #include "nvim/fold.h" +#include "nvim/func_attr.h" #include "nvim/indent.h" #include "nvim/main.h" #include "nvim/mbyte.h" @@ -24,10 +24,11 @@ #include "nvim/memory.h" #include "nvim/move.h" #include "nvim/option.h" +#include "nvim/plines.h" #include "nvim/screen.h" #include "nvim/strings.h" +#include "nvim/vim.h" #include "nvim/window.h" -#include "nvim/buffer.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "plines.c.generated.h" @@ -41,7 +42,34 @@ int plines_win(win_T *wp, linenr_T lnum, bool winheight) { // Check for filler lines above this buffer line. When folded the result // is one line anyway. - return plines_win_nofill(wp, lnum, winheight) + diff_check_fill(wp, lnum); + return plines_win_nofill(wp, lnum, winheight) + win_get_fill(wp, lnum); +} + + +/// Return the number of filler lines above "lnum". +/// +/// @param wp +/// @param lnum +/// +/// @return Number of filler lines above lnum +int win_get_fill(win_T *wp, linenr_T lnum) +{ + int virt_lines = decor_virtual_lines(wp, lnum); + + // be quick when there are no filler lines + if (diffopt_filler()) { + int n = diff_check(wp, lnum); + + if (n > 0) { + return virt_lines+n; + } + } + return virt_lines; +} + +bool win_may_fill(win_T *wp) +{ + return (wp->w_p_diff && diffopt_filler()) || wp->w_buffer->b_virt_line_mark; } /// @param winheight when true limit to window height @@ -71,7 +99,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_u *s; unsigned int col; int width; @@ -107,7 +135,7 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) { // Check for filler lines above this buffer line. When folded the result // is one line anyway. - int lines = diff_check_fill(wp, lnum); + int lines = win_get_fill(wp, lnum); if (!wp->w_p_wrap) { return lines + 1; @@ -159,8 +187,8 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) /// @param[in] cache whether to use the window's cache for folds /// /// @return the total number of screen lines -int plines_win_full(win_T *wp, linenr_T lnum, linenr_T *const nextp, - bool *const foldedp, const bool cache) +int plines_win_full(win_T *wp, linenr_T lnum, linenr_T *const nextp, bool *const foldedp, + const bool cache) { bool folded = hasFoldingWin(wp, lnum, NULL, nextp, cache, NULL); if (foldedp) { @@ -302,8 +330,7 @@ int lbr_chartabsize_adv(char_u *line, char_u **s, colnr_T col) /// @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(win_T *wp, char_u *line, char_u *s, colnr_T col, int *headp) { colnr_T col2; colnr_T col_adj = 0; // col + screen size of tab @@ -326,7 +353,7 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, int size = win_chartabsize(wp, s, col); int c = *s; if (*s == TAB) { - col_adj = size - 1; + col_adj = size - 1; } // If 'linebreak' set check at a blank before a non-blank if the line @@ -343,8 +370,8 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj); if (col >= colmax) { - colmax += col_adj; - n = colmax + win_col_off2(wp); + colmax += col_adj; + n = colmax + win_col_off2(wp); if (n > 0) { colmax += (((col - colmax) / n) + 1) * n - col_adj; diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index 1705ea0c12..606c03f838 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -9,27 +9,27 @@ #include <inttypes.h> #include <stdbool.h> -#include "nvim/buffer.h" -#include "nvim/vim.h" #include "nvim/api/private/helpers.h" #include "nvim/ascii.h" -#include "nvim/eval/typval.h" -#include "nvim/popupmnu.h" +#include "nvim/buffer.h" #include "nvim/charset.h" +#include "nvim/edit.h" +#include "nvim/eval/typval.h" #include "nvim/ex_cmds.h" #include "nvim/memline.h" +#include "nvim/memory.h" #include "nvim/move.h" #include "nvim/option.h" +#include "nvim/popupmnu.h" #include "nvim/screen.h" -#include "nvim/ui_compositor.h" #include "nvim/search.h" #include "nvim/strings.h" -#include "nvim/memory.h" -#include "nvim/window.h" -#include "nvim/edit.h" #include "nvim/ui.h" +#include "nvim/ui_compositor.h" +#include "nvim/vim.h" +#include "nvim/window.h" -static pumitem_T *pum_array = NULL; // items of displayed pum +static pumitem_T *pum_array = NULL; // items of displayed pum static int pum_size; // nr of items in "pum_array" static int pum_selected; // index of selected item or -1 static int pum_first = 0; // index of top item @@ -98,8 +98,7 @@ static void pum_compute_size(void) /// if false, a new item is selected, but the array /// is the same /// @param cmd_startcol only for cmdline mode: column of completed match -void pum_display(pumitem_T *array, int size, int selected, bool array_changed, - int cmd_startcol) +void pum_display(pumitem_T *array, int size, int selected, bool array_changed, int cmd_startcol) { int context_lines; int above_row; @@ -234,7 +233,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, context_lines = 3; } else { context_lines = curwin->w_cline_row - + curwin->w_cline_height - curwin->w_wrow; + + curwin->w_cline_height - curwin->w_wrow; } pum_row = pum_win_row + context_lines; @@ -488,17 +487,17 @@ void pum_redraw(void) s = NULL; switch (round) { - case 1: - p = pum_array[idx].pum_text; - break; + case 1: + p = pum_array[idx].pum_text; + break; - case 2: - p = pum_array[idx].pum_kind; - break; + case 2: + p = pum_array[idx].pum_kind; + break; - case 3: - p = pum_array[idx].pum_extra; - break; + case 3: + p = pum_array[idx].pum_extra; + break; } if (p != NULL) { @@ -515,7 +514,7 @@ void pum_redraw(void) char_u saved = *p; *p = NUL; - st = (char_u *)transstr((const char *)s); + st = (char_u *)transstr((const char *)s, true); *p = saved; if (pum_rl) { diff --git a/src/nvim/profile.c b/src/nvim/profile.c index f9b0bb0a2b..fe7bd2e912 100644 --- a/src/nvim/profile.c +++ b/src/nvim/profile.c @@ -1,17 +1,16 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include <stdio.h> -#include <math.h> #include <assert.h> +#include <math.h> +#include <stdio.h> #include "nvim/assert.h" -#include "nvim/profile.h" -#include "nvim/os/time.h" #include "nvim/func_attr.h" -#include "nvim/os/os_defs.h" - #include "nvim/globals.h" // for the global `time_fd` (startuptime) +#include "nvim/os/os_defs.h" +#include "nvim/os/time.h" +#include "nvim/profile.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "profile.c.generated.h" @@ -97,7 +96,7 @@ proftime_T profile_divide(proftime_T tm, int count) FUNC_ATTR_CONST return profile_zero(); } - return (proftime_T) round((double) tm / (double) count); + return (proftime_T)round((double)tm / (double)count); } /// Adds time `tm2` to `tm1`. diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index e1ee5dc28f..eb0ba874f4 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -8,9 +8,8 @@ #include <stdbool.h> #include <string.h> -#include "nvim/vim.h" +#include "nvim/api/private/helpers.h" #include "nvim/ascii.h" -#include "nvim/quickfix.h" #include "nvim/buffer.h" #include "nvim/charset.h" #include "nvim/cursor.h" @@ -26,29 +25,30 @@ #include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" +#include "nvim/memory.h" #include "nvim/message.h" #include "nvim/misc1.h" -#include "nvim/memory.h" #include "nvim/move.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/quickfix.h" #include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/search.h" #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/ui.h" +#include "nvim/vim.h" #include "nvim/window.h" -#include "nvim/os/os.h" -#include "nvim/os/input.h" -#include "nvim/api/private/helpers.h" struct dir_stack_T { - struct dir_stack_T *next; - char_u *dirname; + struct dir_stack_T *next; + char_u *dirname; }; // For each error the next struct is allocated and linked in a list. @@ -67,7 +67,7 @@ struct qfline_S { char_u *qf_pattern; ///< search pattern for the error char_u *qf_text; ///< description of the error char_u qf_viscol; ///< set to TRUE if qf_col and qf_end_col is - // screen column + // screen column char_u qf_cleared; ///< set to TRUE if line has been deleted char_u qf_type; ///< type of the error (mostly 'E'); 1 for :helpgrep char_u qf_valid; ///< valid error message detected @@ -83,7 +83,7 @@ typedef enum QFLT_QUICKFIX, ///< Quickfix list - global list QFLT_LOCATION, ///< Location list - per window list QFLT_INTERNAL ///< Internal - Temporary list used by - // getqflist()/getloclist() + // getqflist()/getloclist() } qfltype_T; /// Quickfix/Location list definition @@ -93,17 +93,17 @@ typedef enum /// information and entries can be added later using setqflist()/setloclist(). typedef struct qf_list_S { unsigned qf_id; ///< Unique identifier for this list - qfltype_T qfl_type; - qfline_T *qf_start; ///< pointer to the first error - qfline_T *qf_last; ///< pointer to the last error - qfline_T *qf_ptr; ///< pointer to the current error + qfltype_T qfl_type; + qfline_T *qf_start; ///< pointer to the first error + qfline_T *qf_last; ///< pointer to the last error + 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 - char_u *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 - Callback qftf_cb; ///< 'quickfixtextfunc' callback function + char_u *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 + Callback qftf_cb; ///< 'quickfixtextfunc' callback function struct dir_stack_T *qf_dir_stack; char_u *qf_directory; @@ -137,8 +137,8 @@ static unsigned last_qf_id = 0; // Last Used quickfix list id // Structure used to hold the info of one part of 'errorformat' typedef struct efm_S efm_T; struct efm_S { - regprog_T *prog; // pre-formatted part of 'errorformat' - efm_T *next; // pointer to next (NULL if last) + regprog_T *prog; // pre-formatted part of 'errorformat' + efm_T *next; // pointer to next (NULL if last) char_u addr[FMT_PATTERNS]; // indices of used % patterns char_u prefix; // prefix of this format line: // 'D' enter directory @@ -183,12 +183,12 @@ typedef struct { size_t linelen; char_u *growbuf; size_t growbufsiz; - FILE *fd; - typval_T *tv; - char_u *p_str; - list_T *p_list; + FILE *fd; + typval_T *tv; + char_u *p_str; + list_T *p_list; listitem_T *p_li; - buf_T *buf; + buf_T *buf; linenr_T buflnum; linenr_T lnumlast; vimconv_T vc; @@ -201,13 +201,13 @@ typedef struct { size_t errmsglen; long lnum; long end_lnum; - int col; + int col; int end_col; bool use_viscol; char_u *pattern; - int enr; + int enr; char_u type; - bool valid; + bool valid; } qffields_T; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -236,7 +236,7 @@ static char_u *e_no_more_items = (char_u *)N_("E553: No more items"); // Macro to loop through all the items in a quickfix list // Quickfix item index starts from 1, so i below starts at 1 #define FOR_ALL_QFL_ITEMS(qfl, qfp, i) \ - for (i = 1, qfp = qfl->qf_start; /* NOLINT(readability/braces) */ \ + for (i = 1, qfp = qfl->qf_start; /* NOLINT(readability/braces) */ \ !got_int && i <= qfl->qf_count && qfp != NULL; \ i++, qfp = qfp->qf_next) @@ -244,7 +244,7 @@ static char_u *e_no_more_items = (char_u *)N_("E553: No more items"); // Looking up a buffer can be slow if there are many. Remember the last one // to make this a lot faster if there are multiple matches in the same file. static char_u *qf_last_bufname = NULL; -static bufref_T qf_last_bufref = { NULL, 0, 0 }; +static bufref_T qf_last_bufref = { NULL, 0, 0 }; static char *e_current_quickfix_list_was_changed = N_("E925: Current quickfix list was changed"); @@ -258,9 +258,7 @@ static qf_delq_T *qf_delq_head = NULL; /// Process the next line from a file/buffer/list/string and add it /// to the quickfix list 'qfl'. -static int qf_init_process_nextline(qf_list_T *qfl, - efm_T *fmt_first, - qfstate_T *state, +static int qf_init_process_nextline(qf_list_T *qfl, efm_T *fmt_first, qfstate_T *state, qffields_T *fields) { int status; @@ -308,11 +306,10 @@ static int qf_init_process_nextline(qf_list_T *qfl, /// @params enc If non-NULL, encoding used to parse errors /// /// @returns -1 for error, number of errors for success. -int qf_init(win_T *wp, const char_u *restrict efile, - char_u *restrict errorformat, int newlist, +int qf_init(win_T *wp, const char_u *restrict efile, char_u *restrict errorformat, int newlist, const char_u *restrict qf_title, char_u *restrict enc) { - qf_info_T *qi = &ql_info; + qf_info_T *qi = &ql_info; if (wp != NULL) { qi = ll_get_or_alloc_list(wp); @@ -338,7 +335,7 @@ static struct fmtpattern { 't', "." }, { 'm', ".\\+" }, { 'r', ".*" }, - { 'p', "[- .]*" }, // NOLINT(whitespace/tab) + { 'p', "[- .]*"}, // NOLINT(whitespace/tab) { 'v', "\\d\\+" }, { 's', ".\\+" }, { 'o', ".\\+" } @@ -348,14 +345,8 @@ static struct fmtpattern /// See fmt_pat definition above for the list of supported patterns. The /// pattern specifier is supplied in "efmpat". The converted pattern is stored /// in "regpat". Returns a pointer to the location after the pattern. -static char_u * efmpat_to_regpat( - const char_u *efmpat, - char_u *regpat, - efm_T *efminfo, - int idx, - int round, - char_u *errmsg, - size_t errmsglen) +static char_u *efmpat_to_regpat(const char_u *efmpat, char_u *regpat, efm_T *efminfo, int idx, + int round, char_u *errmsg, size_t errmsglen) FUNC_ATTR_NONNULL_ALL { if (efminfo->addr[idx]) { @@ -374,7 +365,7 @@ static char_u * efmpat_to_regpat( EMSG(errmsg); return NULL; } - efminfo->addr[idx] = (char_u)++round; + efminfo->addr[idx] = (char_u)++ round; *regpat++ = '\\'; *regpat++ = '('; #ifdef BACKSLASH_IN_FILENAME @@ -415,13 +406,8 @@ static char_u * efmpat_to_regpat( /// Convert a scanf like format in 'errorformat' to a regular expression. /// Returns a pointer to the location after the pattern. -static char_u * scanf_fmt_to_regpat( - const char_u **pefmp, - const char_u *efm, - int len, - char_u *regpat, - char_u *errmsg, - size_t errmsglen) +static char_u *scanf_fmt_to_regpat(const char_u **pefmp, const char_u *efm, int len, char_u *regpat, + char_u *errmsg, size_t errmsglen) FUNC_ATTR_NONNULL_ALL { const char_u *efmp = *pefmp; @@ -459,8 +445,8 @@ static char_u * scanf_fmt_to_regpat( } /// Analyze/parse an errorformat prefix. -static const char_u *efm_analyze_prefix(const char_u *efmp, efm_T *efminfo, - char_u *errmsg, size_t errmsglen) +static const char_u *efm_analyze_prefix(const char_u *efmp, efm_T *efminfo, char_u *errmsg, + size_t errmsglen) FUNC_ATTR_NONNULL_ALL { if (vim_strchr((char_u *)"+-", *efmp) != NULL) { @@ -480,8 +466,8 @@ static const char_u *efm_analyze_prefix(const char_u *efmp, efm_T *efminfo, // Converts a 'errorformat' string to regular expression pattern -static int efm_to_regpat(const char_u *efm, int len, efm_T *fmt_ptr, - char_u *regpat, char_u *errmsg, size_t errmsglen) +static int efm_to_regpat(const char_u *efm, int len, efm_T *fmt_ptr, char_u *regpat, char_u *errmsg, + size_t errmsglen) FUNC_ATTR_NONNULL_ALL { // Build regexp pattern from current 'errorformat' option @@ -598,7 +584,7 @@ static int efm_option_part_len(char_u *efm) /// Parse the 'errorformat' option. Multiple parts in the 'errorformat' option /// are parsed and converted to regular expressions. Returns information about /// the parsed 'errorformat' option. -static efm_T * parse_efm_option(char_u *efm) +static efm_T *parse_efm_option(char_u *efm) { efm_T *fmt_ptr = NULL; efm_T *fmt_first = NULL; @@ -769,7 +755,7 @@ retry: errno = 0; if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL) { if (errno == EINTR) { - goto retry; + goto retry; } return QF_END_OF_INPUT; } @@ -915,7 +901,7 @@ static bool qf_list_has_valid_entries(qf_list_T *qfl) } /// Return a pointer to a list in the specified quickfix stack -static qf_list_T * qf_get_list(qf_info_T *qi, int idx) +static qf_list_T *qf_get_list(qf_info_T *qi, int idx) FUNC_ATTR_NONNULL_ALL { return &qi->qf_lists[idx]; @@ -923,11 +909,11 @@ static qf_list_T * qf_get_list(qf_info_T *qi, int idx) /// Parse a line and get the quickfix fields. /// Return the QF_ status. -static int qf_parse_line(qf_list_T *qfl, char_u *linebuf, - size_t linelen, efm_T *fmt_first, qffields_T *fields) +static int qf_parse_line(qf_list_T *qfl, char_u *linebuf, size_t linelen, efm_T *fmt_first, + qffields_T *fields) { efm_T *fmt_ptr; - int idx = 0; + int idx = 0; char_u *tail = NULL; int status; @@ -1030,14 +1016,8 @@ static void qf_free_fields(qffields_T *pfields) // Setup the state information used for parsing lines and populating a // quickfix list. -static int qf_setup_state( - qfstate_T *pstate, - char_u *restrict enc, - const char_u *restrict efile, - typval_T *tv, - buf_T *buf, - linenr_T lnumfirst, - linenr_T lnumlast) +static int qf_setup_state(qfstate_T *pstate, char_u *restrict enc, const char_u *restrict efile, + typval_T *tv, buf_T *buf, linenr_T lnumfirst, linenr_T lnumlast) FUNC_ATTR_NONNULL_ARG(1) { pstate->vc.vc_type = CONV_NONE; @@ -1080,38 +1060,32 @@ static void qf_cleanup_state(qfstate_T *pstate) } } -// Read the errorfile "efile" into memory, line by line, building the error -// list. -// Alternative: when "efile" is NULL read errors from buffer "buf". -// Alternative: when "tv" is not NULL get errors from the string or list. -// Always use 'errorformat' from "buf" if there is a local value. -// Then "lnumfirst" and "lnumlast" specify the range of lines to use. -// Set the title of the list to "qf_title". -// Return -1 for error, number of errors for success. -static int -qf_init_ext( - qf_info_T *qi, - int qf_idx, - const char_u *restrict efile, - buf_T *buf, - typval_T *tv, - char_u *restrict errorformat, - bool newlist, // true: start a new error list - linenr_T lnumfirst, // first line number to use - linenr_T lnumlast, // last line number to use - const char_u *restrict qf_title, - char_u *restrict enc -) +/// Read the errorfile "efile" into memory, line by line, building the error +/// list. +/// Alternative: when "efile" is NULL read errors from buffer "buf". +/// Alternative: when "tv" is not NULL get errors from the string or list. +/// Always use 'errorformat' from "buf" if there is a local value. +/// Then "lnumfirst" and "lnumlast" specify the range of lines to use. +/// Set the title of the list to "qf_title". +/// +/// @param newlist true: start a new error list +/// @param lnumfirst first line number to use +/// @param lnumlast last line number to use +/// +/// @return -1 for error, number of errors for success. +static int qf_init_ext(qf_info_T *qi, int qf_idx, const char_u *restrict efile, buf_T *buf, + typval_T *tv, char_u *restrict errorformat, bool newlist, linenr_T lnumfirst, + linenr_T lnumlast, const char_u *restrict qf_title, char_u *restrict enc) FUNC_ATTR_NONNULL_ARG(1) { qf_list_T *qfl; qfstate_T state = { 0 }; qffields_T fields = { 0 }; - qfline_T *old_last = NULL; + qfline_T *old_last = NULL; bool adding = false; - static efm_T *fmt_first = NULL; - char_u *efm; - static char_u *last_efm = NULL; + static efm_T *fmt_first = NULL; + char_u *efm; + static char_u *last_efm = NULL; int retval = -1; // default: return error flag int status; @@ -1237,7 +1211,7 @@ static void qf_store_title(qf_list_T *qfl, const char_u *title) /// that created the quickfix list with the ":" prefix. /// Create a quickfix list title string by prepending ":" to a user command. /// Returns a pointer to a static buffer with the title. -static char_u * qf_cmdtitle(char_u *cmd) +static char_u *qf_cmdtitle(char_u *cmd) { static char_u qftitle_str[IOSIZE]; @@ -1247,7 +1221,7 @@ static char_u * qf_cmdtitle(char_u *cmd) } /// Return a pointer to the current list in the specified quickfix stack -static qf_list_T * qf_get_curlist(qf_info_T *qi) +static qf_list_T *qf_get_curlist(qf_info_T *qi) FUNC_ATTR_NONNULL_ALL { return qf_get_list(qi, qi->qf_curlist); @@ -1276,8 +1250,9 @@ static void qf_new_list(qf_info_T *qi, const char_u *qf_title) qi->qf_lists[i - 1] = qi->qf_lists[i]; } qi->qf_curlist = LISTCOUNT - 1; - } else + } else { qi->qf_curlist = qi->qf_listcount++; + } qfl = qf_get_curlist(qi); memset(qfl, 0, sizeof(qf_list_T)); qf_store_title(qfl, qf_title); @@ -1287,10 +1262,7 @@ static void qf_new_list(qf_info_T *qi, const char_u *qf_title) /// Parse the match for filename ('%f') pattern in regmatch. /// Return the matched value in "fields->namebuf". -static int qf_parse_fmt_f(regmatch_T *rmp, - int midx, - qffields_T *fields, - int prefix) +static int qf_parse_fmt_f(regmatch_T *rmp, int midx, qffields_T *fields, int prefix) { char_u c; @@ -1360,9 +1332,7 @@ static int qf_parse_fmt_t(regmatch_T *rmp, int midx, qffields_T *fields) /// Parse the match for '%+' format pattern. The whole matching line is included /// in the error string. Return the matched line in "fields->errmsg". -static void qf_parse_fmt_plus(const char_u *linebuf, - size_t linelen, - qffields_T *fields) +static void qf_parse_fmt_plus(const char_u *linebuf, size_t linelen, qffields_T *fields) FUNC_ATTR_NONNULL_ALL { if (linelen >= fields->errmsglen) { @@ -1499,9 +1469,8 @@ static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) = { /// fmt_ptr contains the 'efm' format specifiers/prefixes that have a match. /// Returns QF_OK if all the matches are successfully parsed. On failure, /// returns QF_FAIL or QF_NOMEM. -static int qf_parse_match(char_u *linebuf, size_t linelen, efm_T *fmt_ptr, - regmatch_T *regmatch, qffields_T *fields, - int qf_multiline, int qf_multiscan, char_u **tail) +static int qf_parse_match(char_u *linebuf, size_t linelen, efm_T *fmt_ptr, regmatch_T *regmatch, + qffields_T *fields, int qf_multiline, int qf_multiscan, char_u **tail) { char_u idx = fmt_ptr->prefix; int i; @@ -1549,9 +1518,8 @@ static int qf_parse_match(char_u *linebuf, size_t linelen, efm_T *fmt_ptr, /// 'fmt_ptr->prog' and return the matching values in 'fields'. /// Returns QF_OK if the efm format matches completely and the fields are /// successfully copied. Otherwise returns QF_FAIL or QF_NOMEM. -static int qf_parse_get_fields(char_u *linebuf, size_t linelen, efm_T *fmt_ptr, - qffields_T *fields, int qf_multiline, - int qf_multiscan, char_u **tail) +static int qf_parse_get_fields(char_u *linebuf, size_t linelen, efm_T *fmt_ptr, qffields_T *fields, + int qf_multiline, int qf_multiscan, char_u **tail) { regmatch_T regmatch; int status = QF_FAIL; @@ -1611,8 +1579,7 @@ static int qf_parse_dir_pfx(int idx, qffields_T *fields, qf_list_T *qfl) } /// Parse global file name error format prefixes (%O, %P and %Q). -static int qf_parse_file_pfx(int idx, qffields_T *fields, qf_list_T *qfl, - char_u *tail) +static int qf_parse_file_pfx(int idx, qffields_T *fields, qf_list_T *qfl, char_u *tail) { fields->valid = false; if (*fields->namebuf == NUL || os_path_exists(fields->namebuf)) { @@ -1635,8 +1602,7 @@ static int qf_parse_file_pfx(int idx, qffields_T *fields, qf_list_T *qfl, /// Parse a non-error line (a line which doesn't match any of the error /// format in 'efm'). -static int qf_parse_line_nomatch(char_u *linebuf, size_t linelen, - qffields_T *fields) +static int qf_parse_line_nomatch(char_u *linebuf, size_t linelen, qffields_T *fields) { fields->namebuf[0] = NUL; // no match found, remove file name fields->lnum = 0; // don't jump to this line @@ -1714,11 +1680,12 @@ static void locstack_queue_delreq(qf_info_T *qi) static void ll_free_all(qf_info_T **pqi) { int i; - qf_info_T *qi; + qf_info_T *qi; qi = *pqi; - if (qi == NULL) + if (qi == NULL) { return; + } *pqi = NULL; // Remove reference to this list qi->qf_refcount--; @@ -1741,7 +1708,7 @@ static void ll_free_all(qf_info_T **pqi) void qf_free_all(win_T *wp) { int i; - qf_info_T *qi = &ql_info; + qf_info_T *qi = &ql_info; if (wp != NULL) { // location list @@ -1761,7 +1728,7 @@ void qf_free_all(win_T *wp) /// Must always call decr_quickfix_busy() exactly once after this. static void incr_quickfix_busy(void) { - quickfix_busy++; + quickfix_busy++; } /// Safe to free location list stacks. Process any delayed delete requests. @@ -1818,11 +1785,9 @@ void check_quickfix_busy(void) /// @param valid valid entry /// /// @returns QF_OK or QF_FAIL. -static int qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, - char_u *module, int bufnum, char_u *mesg, - long lnum, long end_lnum, int col, int end_col, - char_u vis_col, char_u *pattern, int nr, - char_u type, char_u valid) +static int qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *module, int bufnum, + char_u *mesg, long lnum, long end_lnum, int col, int end_col, + char_u vis_col, char_u *pattern, int nr, char_u type, char_u valid) { qfline_T *qfp = xmalloc(sizeof(qfline_T)); qfline_T **lastp; // pointer to qf_last or NULL @@ -1921,7 +1886,7 @@ static qf_info_T *ll_get_or_alloc_list(win_T *wp) /// 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. -static qf_info_T * qf_cmd_get_stack(exarg_T *eap, int print_emsg) +static qf_info_T *qf_cmd_get_stack(exarg_T *eap, int print_emsg) { qf_info_T *qi = &ql_info; @@ -2140,10 +2105,9 @@ static int qf_get_fnum(qf_list_T *qfl, char_u *directory, char_u *fname ) // Push dirbuf onto the directory stack and return pointer to actual dir or // NULL on error. -static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, - bool is_file_stack) +static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, bool is_file_stack) { - struct dir_stack_T *ds_ptr; + struct dir_stack_T *ds_ptr; // allocate new stack element and hook it in struct dir_stack_T *ds_new = xmalloc(sizeof(struct dir_stack_T)); @@ -2165,9 +2129,10 @@ static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, while (ds_new) { xfree((*stackptr)->dirname); (*stackptr)->dirname = (char_u *)concat_fnames((char *)ds_new->dirname, - (char *)dirbuf, TRUE); - if (os_isdir((*stackptr)->dirname)) + (char *)dirbuf, TRUE); + if (os_isdir((*stackptr)->dirname)) { break; + } ds_new = ds_new->next; } @@ -2187,9 +2152,9 @@ static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, } } - if ((*stackptr)->dirname != NULL) + if ((*stackptr)->dirname != NULL) { return (*stackptr)->dirname; - else { + } else { ds_ptr = *stackptr; *stackptr = (*stackptr)->next; xfree(ds_ptr); @@ -2202,7 +2167,7 @@ static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, // stack is empty static char_u *qf_pop_dir(struct dir_stack_T **stackptr) { - struct dir_stack_T *ds_ptr; + struct dir_stack_T *ds_ptr; // TODO(vim): Should we check if dirbuf is the directory on top of the stack? // What to do if it isn't? @@ -2222,7 +2187,7 @@ static char_u *qf_pop_dir(struct dir_stack_T **stackptr) // clean up directory stack static void qf_clean_dir_stack(struct dir_stack_T **stackptr) { - struct dir_stack_T *ds_ptr; + struct dir_stack_T *ds_ptr; while ((ds_ptr = *stackptr) != NULL) { *stackptr = (*stackptr)->next; @@ -2251,9 +2216,9 @@ static void qf_clean_dir_stack(struct dir_stack_T **stackptr) /// qf_guess_filepath will return NULL. static char_u *qf_guess_filepath(qf_list_T *qfl, char_u *filename) { - struct dir_stack_T *ds_ptr; - struct dir_stack_T *ds_tmp; - char_u *fullname; + struct dir_stack_T *ds_ptr; + struct dir_stack_T *ds_tmp; + char_u *fullname; // no dirs on the stack - there's nothing we can do if (qfl->qf_dir_stack == NULL) { @@ -2332,8 +2297,7 @@ static bool is_qf_entry_present(qf_list_T *qfl, qfline_T *qf_ptr) /// Get the next valid entry in the current quickfix/location list. The search /// starts from the current entry. Returns NULL on failure. -static qfline_T *get_next_valid_entry(qf_list_T *qfl, qfline_T *qf_ptr, - int *qf_index, int dir) +static qfline_T *get_next_valid_entry(qf_list_T *qfl, qfline_T *qf_ptr, int *qf_index, int dir) { int idx = *qf_index; int old_qf_fnum = qf_ptr->qf_fnum; @@ -2353,8 +2317,7 @@ static qfline_T *get_next_valid_entry(qf_list_T *qfl, qfline_T *qf_ptr, /// Get the previous valid entry in the current quickfix/location list. The /// search starts from the current entry. Returns NULL on failure. -static qfline_T *get_prev_valid_entry(qf_list_T *qfl, qfline_T *qf_ptr, - int *qf_index, int dir) +static qfline_T *get_prev_valid_entry(qf_list_T *qfl, qfline_T *qf_ptr, int *qf_index, int dir) { int idx = *qf_index; int old_qf_fnum = qf_ptr->qf_fnum; @@ -2376,8 +2339,7 @@ static qfline_T *get_prev_valid_entry(qf_list_T *qfl, qfline_T *qf_ptr, /// the quickfix list. /// dir == FORWARD or FORWARD_FILE: next valid entry /// dir == BACKWARD or BACKWARD_FILE: previous valid entry -static qfline_T *get_nth_valid_entry(qf_list_T *qfl, int errornr, - int dir, int *new_qfidx) +static qfline_T *get_nth_valid_entry(qf_list_T *qfl, int errornr, int dir, int *new_qfidx) { qfline_T *qf_ptr = qfl->qf_ptr; int qf_idx = qfl->qf_index; @@ -2442,20 +2404,19 @@ static qfline_T *get_nth_entry(qf_list_T *qfl, int errornr, int *new_qfidx) /// specifies the direction (FORWARD/BACKWARD/FORWARD_FILE/BACKWARD_FILE). /// Returns a pointer to the entry and the index of the new entry is stored in /// 'new_qfidx'. -static qfline_T * qf_get_entry(qf_list_T *qfl, int errornr, - int dir, int *new_qfidx) +static qfline_T *qf_get_entry(qf_list_T *qfl, int errornr, int dir, int *new_qfidx) { - qfline_T *qf_ptr = qfl->qf_ptr; - int qfidx = qfl->qf_index; + qfline_T *qf_ptr = qfl->qf_ptr; + int qfidx = qfl->qf_index; - if (dir != 0) { // next/prev valid entry - qf_ptr = get_nth_valid_entry(qfl, errornr, dir, &qfidx); - } else if (errornr != 0) { // go to specified number - qf_ptr = get_nth_entry(qfl, errornr, &qfidx); - } + if (dir != 0) { // next/prev valid entry + qf_ptr = get_nth_valid_entry(qfl, errornr, dir, &qfidx); + } else if (errornr != 0) { // go to specified number + qf_ptr = get_nth_entry(qfl, errornr, &qfidx); + } - *new_qfidx = qfidx; - return qf_ptr; + *new_qfidx = qfidx; + return qf_ptr; } // Find a window displaying a Vim help file. @@ -2596,8 +2557,7 @@ static int qf_open_new_file_win(qf_info_T *ll_ref) // to the window just above the location list window. This is used for opening // a file from a location window and not from a quickfix window. If some usable // window is previously found, then it is supplied in 'use_win'. -static void qf_goto_win_with_ll_file(win_T *use_win, int qf_fnum, - qf_info_T *ll_ref) +static void qf_goto_win_with_ll_file(win_T *use_win, int qf_fnum, qf_info_T *ll_ref) { win_T *win = use_win; @@ -2684,8 +2644,7 @@ static void qf_goto_win_with_qfl_file(int qf_fnum) // window, jump to it. Otherwise open a new window to display the file. If // 'newwin' is true, then always open a new window. This is called from either // a quickfix or a location list window. -static int qf_jump_to_usable_window(int qf_fnum, bool newwin, - int *opened_window) +static int qf_jump_to_usable_window(int qf_fnum, bool newwin, int *opened_window) { win_T *usable_wp = NULL; bool usable_win = false; @@ -2735,8 +2694,8 @@ static int qf_jump_to_usable_window(int qf_fnum, bool newwin, } /// Edit the selected file or help file. -static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, - win_T *oldwin, int *opened_window) +static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, win_T *oldwin, + int *opened_window) { qf_list_T *qfl = qf_get_curlist(qi); long old_changetick = qfl->qf_changedtick; @@ -2789,8 +2748,7 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, /// Go to the error line in the current file using either line/column number or /// a search pattern. -static void qf_jump_goto_line(linenr_T qf_lnum, int qf_col, char_u qf_viscol, - char_u *qf_pattern) +static void qf_jump_goto_line(linenr_T qf_lnum, int qf_col, char_u qf_viscol, char_u *qf_pattern) { linenr_T i; @@ -2826,8 +2784,8 @@ static void qf_jump_goto_line(linenr_T qf_lnum, int qf_col, char_u qf_viscol, } /// Display quickfix list index and size message -static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, - buf_T *old_curbuf, linenr_T old_lnum) +static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf_T *old_curbuf, + linenr_T old_lnum) { // Update the screen before showing the message, unless the screen // scrolled up. @@ -2862,15 +2820,14 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, /// Returns OK if successfully jumped or opened a window. Returns FAIL if not /// able to jump/open a window. Returns NOTDONE if a file is not associated /// with the entry. -static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, - int *opened_window) +static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, int *opened_window) { qf_list_T *qfl = qf_get_curlist(qi); long old_changetick = qfl->qf_changedtick; int old_qf_curlist = qi->qf_curlist; qfltype_T qfl_type = qfl->qfl_type; - // For ":helpgrep" find a help window or open one. + // For ":helpgrep" find a help window or open one. if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0)) { if (jump_to_help_window(qi, newwin, opened_window) == FAIL) { return FAIL; @@ -2921,9 +2878,8 @@ static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, /// Returns OK on success and FAIL on failing to open the file/buffer. Returns /// NOTDONE if the quickfix/location list is freed by an autocmd when opening /// the file. -static int qf_jump_to_buffer(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, - int forceit, win_T *oldwin, int *opened_window, - int openfold, int print_message) +static int qf_jump_to_buffer(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, int forceit, + win_T *oldwin, int *opened_window, int openfold, int print_message) { buf_T *old_curbuf; linenr_T old_lnum; @@ -2975,8 +2931,7 @@ void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit) // else if "errornr" is zero, redisplay the same line // If 'forceit' is true, then can discard changes to the current buffer. // 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) +static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, bool newwin) { qf_list_T *qfl; qfline_T *qf_ptr; @@ -2991,8 +2946,9 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, const bool old_KeyTyped = KeyTyped; // getting file may reset it int retval = OK; - if (qi == NULL) + if (qi == NULL) { qi = &ql_info; + } if (qf_stack_empty(qi) || qf_list_empty(qf_get_curlist(qi))) { EMSG(_(e_quickfix)); @@ -3042,8 +2998,8 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, win_close(curwin, true); // Close opened window } if (qf_ptr != NULL && qf_ptr->qf_fnum != 0) { - // Couldn't open file, so put index back where it was. This could - // happen if the file was readonly and we changed something. + // Couldn't open file, so put index back where it was. This could + // happen if the file was readonly and we changed something. failed: qf_ptr = old_qf_ptr; qf_index = old_qf_index; @@ -3158,9 +3114,9 @@ void qf_list(exarg_T *eap) int i; int idx1 = 1; int idx2 = -1; - char_u *arg = eap->arg; - int all = eap->forceit; // if not :cl!, only show - // recognised errors + char_u *arg = eap->arg; + int all = eap->forceit; // if not :cl!, only show + // recognised errors qf_info_T *qi; if ((qi = qf_cmd_get_stack(eap, true)) == NULL) { @@ -3203,15 +3159,15 @@ void qf_list(exarg_T *eap) // that this depends on syntax items defined in the qf.vim syntax file qfFileAttr = syn_name2attr((char_u *)"qfFileName"); if (qfFileAttr == 0) { - qfFileAttr = HL_ATTR(HLF_D); + qfFileAttr = HL_ATTR(HLF_D); } qfSepAttr = syn_name2attr((char_u *)"qfSeparator"); if (qfSepAttr == 0) { - qfSepAttr = HL_ATTR(HLF_D); + qfSepAttr = HL_ATTR(HLF_D); } qfLineAttr = syn_name2attr((char_u *)"qfLineNr"); if (qfLineAttr == 0) { - qfLineAttr = HL_ATTR(HLF_N); + qfLineAttr = HL_ATTR(HLF_N); } if (qfl->qf_nonevalid) { @@ -3227,8 +3183,7 @@ void qf_list(exarg_T *eap) // Remove newlines and leading whitespace from an error message. // Put the result in "buf[bufsize]". -static void qf_fmt_text(const char_u *restrict text, char_u *restrict buf, - int bufsize) +static void qf_fmt_text(const char_u *restrict text, char_u *restrict buf, int bufsize) FUNC_ATTR_NONNULL_ALL { int i; @@ -3237,11 +3192,14 @@ static void qf_fmt_text(const char_u *restrict text, char_u *restrict buf, for (i = 0; *p != NUL && i < bufsize - 1; ++i) { if (*p == '\n') { buf[i] = ' '; - while (*++p != NUL) - if (!ascii_iswhite(*p) && *p != '\n') + while (*++p != NUL) { + if (!ascii_iswhite(*p) && *p != '\n') { break; - } else + } + } + } else { buf[i] = *p++; + } } buf[i] = NUL; } @@ -3290,8 +3248,8 @@ static void qf_msg(qf_info_T *qi, int which, char *lead) size_t len = STRLEN(buf); if (len < 34) { - memset(buf + len, ' ', 34 - len); - buf[34] = NUL; + memset(buf + len, ' ', 34 - len); + buf[34] = NUL; } xstrlcat((char *)buf, title, IOSIZE); } @@ -3374,8 +3332,8 @@ void qf_history(exarg_T *eap) /// associated with the list like context and title are not freed. static void qf_free_items(qf_list_T *qfl) { - qfline_T *qfp; - qfline_T *qfpnext; + qfline_T *qfp; + qfline_T *qfpnext; bool stop = false; while (qfl->qf_count && qfl->qf_start != NULL) { @@ -3430,13 +3388,12 @@ static void qf_free(qf_list_T *qfl) } // qf_mark_adjust: adjust marks -bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, - long amount_after) +bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long amount_after) { int i; - qfline_T *qfp; + qfline_T *qfp; int idx; - qf_info_T *qi = &ql_info; + qf_info_T *qi = &ql_info; bool found_one = false; int buf_has_flag = wp == NULL ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; @@ -3457,12 +3414,14 @@ bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, if (qfp->qf_fnum == curbuf->b_fnum) { found_one = true; if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2) { - if (amount == MAXLNUM) + if (amount == MAXLNUM) { qfp->qf_cleared = TRUE; - else + } else { qfp->qf_lnum += amount; - } else if (amount_after && qfp->qf_lnum > line2) + } + } else if (amount_after && qfp->qf_lnum > line2) { qfp->qf_lnum += amount_after; + } } } } @@ -3490,7 +3449,7 @@ static char_u *qf_types(int c, int nr) { static char_u buf[20]; static char_u cc[3]; - char_u *p; + char_u *p; if (c == 'W' || c == 'w') { p = (char_u *)" warning"; @@ -3509,8 +3468,9 @@ static char_u *qf_types(int c, int nr) p = cc; } - if (nr <= 0) + if (nr <= 0) { return p; + } sprintf((char *)buf, "%s %3d", (char *)p, nr); return buf; @@ -3520,7 +3480,7 @@ static char_u *qf_types(int c, int nr) // When "split" is true: Open the entry/result under the cursor in a new window. void qf_view_result(bool split) { - qf_info_T *qi = &ql_info; + qf_info_T *qi = &ql_info; if (!bt_quickfix(curbuf)) { return; @@ -3549,9 +3509,9 @@ void qf_view_result(bool split) // close it if not. void ex_cwindow(exarg_T *eap) { - qf_info_T *qi; - qf_list_T *qfl; - win_T *win; + qf_info_T *qi; + qf_list_T *qfl; + win_T *win; if ((qi = qf_cmd_get_stack(eap, true)) == NULL) { return; @@ -3596,8 +3556,7 @@ void ex_cclose(exarg_T *eap) // Goto a quickfix or location list window (if present). // Returns OK if the window is found, FAIL otherwise. -static int qf_goto_cwindow(const qf_info_T *qi, bool resize, int sz, - bool vertsplit) +static int qf_goto_cwindow(const qf_info_T *qi, bool resize, int sz, bool vertsplit) { win_T *const win = qf_find_win(qi); if (win == NULL) { @@ -3725,8 +3684,8 @@ static void qf_set_title_var(qf_list_T *qfl) /// ":lopen": open a window that shows the location list. void ex_copen(exarg_T *eap) { - qf_info_T *qi; - qf_list_T *qfl; + qf_info_T *qi; + qf_list_T *qfl; int height; int status = FAIL; int lnum; @@ -3812,7 +3771,7 @@ void ex_cbottom(exarg_T *eap) // window). linenr_T qf_current_entry(win_T *wp) { - qf_info_T *qi = &ql_info; + qf_info_T *qi = &ql_info; if (IS_LL_WINDOW(wp)) { // In the location list window, use the referenced location list @@ -3822,14 +3781,13 @@ linenr_T qf_current_entry(win_T *wp) return qf_get_curlist(qi)->qf_index; } -// Update the cursor position in the quickfix window to the current error. -// Return TRUE if there is a quickfix window. -static int qf_win_pos_update( - qf_info_T *qi, - int old_qf_index // previous qf_index or zero -) +/// Update the cursor position in the quickfix window to the current error. +/// Return TRUE if there is a quickfix window. +/// +/// @param old_qf_index previous qf_index or zero +static int qf_win_pos_update(qf_info_T *qi, int old_qf_index) { - win_T *win; + win_T *win; int qf_index = qf_get_curlist(qi)->qf_index; // Put the cursor on the current error in the quickfix window, so that @@ -3954,8 +3912,8 @@ static void qf_update_win_titlevar(qf_info_T *qi) // Find the quickfix buffer. If it exists, update the contents. static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) { - buf_T *buf; - win_T *win; + buf_T *buf; + win_T *win; aco_save_T aco; // Check if a buffer for the quickfix list exists. Update it. @@ -4002,9 +3960,8 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) } // Add an error line to the quickfix buffer. -static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, - const qfline_T *qfp, char_u *dirname, - char_u *qftf_str, bool first_bufline) +static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfline_T *qfp, + char_u *dirname, char_u *qftf_str, bool first_bufline) FUNC_ATTR_NONNULL_ARG(1, 2, 4, 5) { int len; @@ -4076,10 +4033,7 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, // Call the 'quickfixtextfunc' function to get the list of lines to display in // the quickfix window for the entries 'start_idx' to 'end_idx'. -static list_T *call_qftf_func(qf_list_T *qfl, - int qf_winid, - long start_idx, - long end_idx) +static list_T *call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx) { Callback *cb = &qftf_cb; list_T *qftf_list = NULL; @@ -4126,12 +4080,11 @@ static list_T *call_qftf_func(qf_list_T *qfl, /// If "old_last" is not NULL append the items after this one. /// When "old_last" is NULL then "buf" must equal "curbuf"! Because ml_delete() /// is used and autocommands will be triggered. -static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, - int qf_winid) +static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid) FUNC_ATTR_NONNULL_ARG(2) { linenr_T lnum; - qfline_T *qfp; + qfline_T *qfp; const bool old_KeyTyped = KeyTyped; list_T *qftf_list = NULL; listitem_T *qftf_li = NULL; @@ -4150,11 +4103,11 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, // Check if there is anything to display if (qfl != NULL) { - char_u dirname[MAXPATHL]; - int prev_bufnr = -1; - bool invalid_val = false; + char_u dirname[MAXPATHL]; + int prev_bufnr = -1; + bool invalid_val = false; - *dirname = NUL; + *dirname = NUL; // Add one line for each error if (old_last == NULL) { @@ -4235,7 +4188,7 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, static void qf_list_changed(qf_list_T *qfl) { - qfl->qf_changedtick++; + qfl->qf_changedtick++; } /// Return the quickfix/location list number with the given identifier. @@ -4291,7 +4244,7 @@ int grep_internal(cmdidx_T cmdidx) || cmdidx == CMD_grepadd || cmdidx == CMD_lgrepadd) && STRCMP("internal", - *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0; + *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0; } // Return the make/grep autocmd name. @@ -4299,20 +4252,20 @@ static char_u *make_get_auname(cmdidx_T cmdidx) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { switch (cmdidx) { - case CMD_make: - return (char_u *)"make"; - case CMD_lmake: - return (char_u *)"lmake"; - case CMD_grep: - return (char_u *)"grep"; - case CMD_lgrep: - return (char_u *)"lgrep"; - case CMD_grepadd: - return (char_u *)"grepadd"; - case CMD_lgrepadd: - return (char_u *)"lgrepadd"; - default: - return NULL; + case CMD_make: + return (char_u *)"make"; + case CMD_lmake: + return (char_u *)"lmake"; + case CMD_grep: + return (char_u *)"grep"; + case CMD_lgrep: + return (char_u *)"lgrep"; + case CMD_grepadd: + return (char_u *)"grepadd"; + case CMD_lgrepadd: + return (char_u *)"lgrepadd"; + default: + return NULL; } } @@ -4349,9 +4302,9 @@ static char *make_get_fullcmd(const char_u *makecmd, const char_u *fname) // Used for ":make", ":lmake", ":grep", ":lgrep", ":grepadd", and ":lgrepadd" void ex_make(exarg_T *eap) { - char_u *fname; - win_T *wp = NULL; - qf_info_T *qi = &ql_info; + char_u *fname; + win_T *wp = NULL; + qf_info_T *qi = &ql_info; int res; char_u *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc; @@ -4375,8 +4328,9 @@ void ex_make(exarg_T *eap) autowrite_all(); fname = get_mef_name(); - if (fname == NULL) + if (fname == NULL) { return; + } os_remove((char *)fname); // in case it's not unique char *const cmd = make_get_fullcmd(eap->arg, fname); @@ -4422,24 +4376,28 @@ cleanup: // Returns NULL for error. static char_u *get_mef_name(void) { - char_u *p; - char_u *name; + char_u *p; + char_u *name; static int start = -1; static int off = 0; if (*p_mef == NUL) { name = vim_tempname(); - if (name == NULL) + if (name == NULL) { EMSG(_(e_notmp)); + } return name; } - for (p = p_mef; *p; ++p) - if (p[0] == '#' && p[1] == '#') + for (p = p_mef; *p; ++p) { + if (p[0] == '#' && p[1] == '#') { break; + } + } - if (*p == NUL) + if (*p == NUL) { return vim_strsave(p_mef); + } // Keep trying until the name doesn't exist yet. for (;; ) { @@ -4613,7 +4571,7 @@ static size_t qf_get_nth_valid_entry(qf_list_T *qfl, size_t n, int fdo) /// ":cdo", ":ldo", ":cfdo" and ":lfdo". void ex_cc(exarg_T *eap) { - qf_info_T *qi; + qf_info_T *qi; if ((qi = qf_cmd_get_stack(eap, true)) == NULL) { return; @@ -4624,19 +4582,19 @@ void ex_cc(exarg_T *eap) errornr = (int)eap->line2; } else { switch (eap->cmdidx) { - case CMD_cc: - case CMD_ll: - errornr = 0; - break; - case CMD_crewind: - case CMD_lrewind: - case CMD_cfirst: - case CMD_lfirst: - errornr = 1; - break; - default: - errornr = 32767; - break; + case CMD_cc: + case CMD_ll: + errornr = 0; + break; + case CMD_crewind: + case CMD_lrewind: + case CMD_cfirst: + case CMD_lfirst: + errornr = 1; + break; + default: + errornr = 32767; + break; } } @@ -4651,9 +4609,8 @@ void ex_cc(exarg_T *eap) } else { n = 1; } - size_t valid_entry = qf_get_nth_valid_entry( - qf_get_curlist(qi), n, - eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo); + size_t valid_entry = qf_get_nth_valid_entry(qf_get_curlist(qi), n, + eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo); assert(valid_entry <= INT_MAX); errornr = (int)valid_entry; } @@ -4666,7 +4623,7 @@ void ex_cc(exarg_T *eap) /// ":cdo", ":ldo", ":cfdo" and ":lfdo". void ex_cnext(exarg_T *eap) { - qf_info_T *qi; + qf_info_T *qi; if ((qi = qf_cmd_get_stack(eap, true)) == NULL) { return; @@ -4684,31 +4641,31 @@ void ex_cnext(exarg_T *eap) // Depending on the command jump to either next or previous entry/file. Direction dir; switch (eap->cmdidx) { - case CMD_cprevious: - case CMD_lprevious: - case CMD_cNext: - case CMD_lNext: - dir = BACKWARD; - break; - case CMD_cnfile: - case CMD_lnfile: - case CMD_cfdo: - case CMD_lfdo: - dir = FORWARD_FILE; - break; - case CMD_cpfile: - case CMD_lpfile: - case CMD_cNfile: - case CMD_lNfile: - dir = BACKWARD_FILE; - break; - case CMD_cnext: - case CMD_lnext: - case CMD_cdo: - case CMD_ldo: - default: - dir = FORWARD; - break; + case CMD_cprevious: + case CMD_lprevious: + case CMD_cNext: + case CMD_lNext: + dir = BACKWARD; + break; + case CMD_cnfile: + case CMD_lnfile: + case CMD_cfdo: + case CMD_lfdo: + dir = FORWARD_FILE; + break; + case CMD_cpfile: + case CMD_lpfile: + case CMD_cNfile: + case CMD_lNfile: + dir = BACKWARD_FILE; + break; + case CMD_cnext: + case CMD_lnext: + case CMD_cdo: + case CMD_ldo: + default: + dir = FORWARD; + break; } qf_jump(qi, dir, errornr, eap->forceit); @@ -4717,9 +4674,7 @@ void ex_cnext(exarg_T *eap) /// Find the first entry in the quickfix list 'qfl' from buffer 'bnr'. /// The index of the entry is stored in 'errornr'. /// Returns NULL if an entry is not found. -static qfline_T *qf_find_first_entry_in_buf(qf_list_T *qfl, - int bnr, - int *errornr) +static qfline_T *qf_find_first_entry_in_buf(qf_list_T *qfl, int bnr, int *errornr) { qfline_T *qfp = NULL; int idx = 0; @@ -4738,7 +4693,7 @@ static qfline_T *qf_find_first_entry_in_buf(qf_list_T *qfl, /// Find the first quickfix entry on the same line as 'entry'. Updates 'errornr' /// with the error number for the first entry. Assumes the entries are sorted in /// the quickfix list by line number. -static qfline_T * qf_find_first_entry_on_line(qfline_T *entry, int *errornr) +static qfline_T *qf_find_first_entry_on_line(qfline_T *entry, int *errornr) { while (!got_int && entry->qf_prev != NULL @@ -4754,7 +4709,7 @@ static qfline_T * qf_find_first_entry_on_line(qfline_T *entry, int *errornr) /// Find the last quickfix entry on the same line as 'entry'. Updates 'errornr' /// with the error number for the last entry. Assumes the entries are sorted in /// the quickfix list by line number. -static qfline_T * qf_find_last_entry_on_line(qfline_T *entry, int *errornr) +static qfline_T *qf_find_last_entry_on_line(qfline_T *entry, int *errornr) { while (!got_int && entry->qf_next != NULL @@ -4770,57 +4725,53 @@ static qfline_T * qf_find_last_entry_on_line(qfline_T *entry, int *errornr) // Returns true if the specified quickfix entry is // after the given line (linewise is true) // or after the line and column. -static bool qf_entry_after_pos(const qfline_T *qfp, const pos_T *pos, - bool linewise) +static bool qf_entry_after_pos(const qfline_T *qfp, const pos_T *pos, bool linewise) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (linewise) { return qfp->qf_lnum > pos->lnum; } return qfp->qf_lnum > pos->lnum - || (qfp->qf_lnum == pos->lnum && qfp->qf_col > pos->col); + || (qfp->qf_lnum == pos->lnum && qfp->qf_col > pos->col); } // Returns true if the specified quickfix entry is // before the given line (linewise is true) // or before the line and column. -static bool qf_entry_before_pos(const qfline_T *qfp, const pos_T *pos, - bool linewise) +static bool qf_entry_before_pos(const qfline_T *qfp, const pos_T *pos, bool linewise) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (linewise) { return qfp->qf_lnum < pos->lnum; } return qfp->qf_lnum < pos->lnum - || (qfp->qf_lnum == pos->lnum && qfp->qf_col < pos->col); + || (qfp->qf_lnum == pos->lnum && qfp->qf_col < pos->col); } // Returns true if the specified quickfix entry is // on or after the given line (linewise is true) // or on or after the line and column. -static bool qf_entry_on_or_after_pos(const qfline_T *qfp, const pos_T *pos, - bool linewise) +static bool qf_entry_on_or_after_pos(const qfline_T *qfp, const pos_T *pos, bool linewise) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (linewise) { return qfp->qf_lnum >= pos->lnum; } return qfp->qf_lnum > pos->lnum - || (qfp->qf_lnum == pos->lnum && qfp->qf_col >= pos->col); + || (qfp->qf_lnum == pos->lnum && qfp->qf_col >= pos->col); } // Returns true if the specified quickfix entry is // on or before the given line (linewise is true) // or on or before the line and column. -static bool qf_entry_on_or_before_pos(const qfline_T *qfp, const pos_T *pos, - bool linewise) +static bool qf_entry_on_or_before_pos(const qfline_T *qfp, const pos_T *pos, bool linewise) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (linewise) { return qfp->qf_lnum <= pos->lnum; } return qfp->qf_lnum < pos->lnum - || (qfp->qf_lnum == pos->lnum && qfp->qf_col <= pos->col); + || (qfp->qf_lnum == pos->lnum && qfp->qf_col <= pos->col); } /// Find the first quickfix entry after position 'pos' in buffer 'bnr'. @@ -4830,13 +4781,8 @@ static bool qf_entry_on_or_before_pos(const qfline_T *qfp, const pos_T *pos, /// 'qfp' points to the very first entry in the buffer and 'errornr' is the /// index of the very first entry in the quickfix list. /// Returns NULL if an entry is not found after 'pos'. -static qfline_T *qf_find_entry_after_pos( - int bnr, - const pos_T *pos, - bool linewise, - qfline_T *qfp, - int *errornr -) +static qfline_T *qf_find_entry_after_pos(int bnr, const pos_T *pos, bool linewise, qfline_T *qfp, + int *errornr) FUNC_ATTR_NONNULL_ALL { if (qf_entry_after_pos(qfp, pos, linewise)) { @@ -4871,13 +4817,8 @@ static qfline_T *qf_find_entry_after_pos( /// 'qfp' points to the very first entry in the buffer and 'errornr' is the /// index of the very first entry in the quickfix list. /// Returns NULL if an entry is not found before 'pos'. -static qfline_T *qf_find_entry_before_pos( - int bnr, - const pos_T *pos, - bool linewise, - qfline_T *qfp, - int *errornr -) +static qfline_T *qf_find_entry_before_pos(int bnr, const pos_T *pos, bool linewise, qfline_T *qfp, + int *errornr) FUNC_ATTR_NONNULL_ALL { // Find the entry just before the position 'pos' @@ -4902,14 +4843,8 @@ static qfline_T *qf_find_entry_before_pos( /// Find a quickfix entry in 'qfl' closest to position 'pos' in buffer 'bnr' in /// the direction 'dir'. -static qfline_T *qf_find_closest_entry( - qf_list_T *qfl, - int bnr, - const pos_T *pos, - Direction dir, - bool linewise, - int *errornr -) +static qfline_T *qf_find_closest_entry(qf_list_T *qfl, int bnr, const pos_T *pos, Direction dir, + bool linewise, int *errornr) FUNC_ATTR_NONNULL_ALL { qfline_T *qfp; @@ -4934,8 +4869,7 @@ static qfline_T *qf_find_closest_entry( /// Get the nth quickfix entry below the specified entry. Searches forward in /// the list. If linewise is true, then treat multiple entries on a single line /// as one. -static void qf_get_nth_below_entry(qfline_T *entry, linenr_T n, - bool linewise, int *errornr) +static void qf_get_nth_below_entry(qfline_T *entry, linenr_T n, bool linewise, int *errornr) FUNC_ATTR_NONNULL_ALL { while (n-- > 0 && !got_int) { @@ -4966,8 +4900,7 @@ static void qf_get_nth_below_entry(qfline_T *entry, linenr_T n, /// 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 /// as one. -static void qf_get_nth_above_entry(qfline_T *entry, linenr_T n, - bool linewise, int *errornr) +static void qf_get_nth_above_entry(qfline_T *entry, linenr_T n, bool linewise, int *errornr) FUNC_ATTR_NONNULL_ALL { while (n-- > 0 && !got_int) { @@ -4988,14 +4921,8 @@ static void qf_get_nth_above_entry(qfline_T *entry, linenr_T n, /// Find the n'th quickfix entry adjacent to position 'pos' in buffer 'bnr' in /// the specified direction. Returns the error number in the quickfix list or 0 /// if an entry is not found. -static int qf_find_nth_adj_entry( - qf_list_T *qfl, - int bnr, - pos_T *pos, - linenr_T n, - Direction dir, - bool linewise -) +static int qf_find_nth_adj_entry(qf_list_T *qfl, int bnr, pos_T *pos, linenr_T n, Direction dir, + bool linewise) FUNC_ATTR_NONNULL_ALL { int errornr; @@ -5072,16 +4999,15 @@ void ex_cbelow(exarg_T *eap) // A quickfix entry column number is 1 based whereas cursor column // number is 0 based. Adjust the column number. pos.col++; - const int errornr = qf_find_nth_adj_entry( - qfl, - curbuf->b_fnum, - &pos, - eap->addr_count > 0 ? eap->line2 : 0, - dir, - eap->cmdidx == CMD_cbelow - || eap->cmdidx == CMD_lbelow - || eap->cmdidx == CMD_cabove - || eap->cmdidx == CMD_labove); + const int errornr = qf_find_nth_adj_entry(qfl, + curbuf->b_fnum, + &pos, + eap->addr_count > 0 ? eap->line2 : 0, + dir, + eap->cmdidx == CMD_cbelow + || eap->cmdidx == CMD_lbelow + || eap->cmdidx == CMD_cabove + || eap->cmdidx == CMD_labove); if (errornr > 0) { qf_jump(qi, 0, errornr, false); @@ -5092,16 +5018,23 @@ void ex_cbelow(exarg_T *eap) /// Return the autocmd name for the :cfile Ex commands -static char_u * cfile_get_auname(cmdidx_T cmdidx) +static char_u *cfile_get_auname(cmdidx_T cmdidx) { switch (cmdidx) { - case CMD_cfile: return (char_u *)"cfile"; - case CMD_cgetfile: return (char_u *)"cgetfile"; - case CMD_caddfile: return (char_u *)"caddfile"; - case CMD_lfile: return (char_u *)"lfile"; - case CMD_lgetfile: return (char_u *)"lgetfile"; - case CMD_laddfile: return (char_u *)"laddfile"; - default: return NULL; + case CMD_cfile: + return (char_u *)"cfile"; + case CMD_cgetfile: + return (char_u *)"cgetfile"; + case CMD_caddfile: + return (char_u *)"caddfile"; + case CMD_lfile: + return (char_u *)"lfile"; + case CMD_lgetfile: + return (char_u *)"lgetfile"; + case CMD_laddfile: + return (char_u *)"laddfile"; + default: + return NULL; } } @@ -5110,9 +5043,9 @@ static char_u * cfile_get_auname(cmdidx_T cmdidx) // ":lfile"/":lgetfile"/":laddfile" commands. void ex_cfile(exarg_T *eap) { - win_T *wp = NULL; - qf_info_T *qi = &ql_info; - char_u *au_name = NULL; + win_T *wp = NULL; + qf_info_T *qi = &ql_info; + char_u *au_name = NULL; au_name = cfile_get_auname(eap->cmdidx); if (au_name != NULL @@ -5173,15 +5106,24 @@ void ex_cfile(exarg_T *eap) static char_u *vgr_get_auname(cmdidx_T cmdidx) { switch (cmdidx) { - case CMD_vimgrep: return (char_u *)"vimgrep"; - case CMD_lvimgrep: return (char_u *)"lvimgrep"; - case CMD_vimgrepadd: return (char_u *)"vimgrepadd"; - case CMD_lvimgrepadd: return (char_u *)"lvimgrepadd"; - case CMD_grep: return (char_u *)"grep"; - case CMD_lgrep: return (char_u *)"lgrep"; - case CMD_grepadd: return (char_u *)"grepadd"; - case CMD_lgrepadd: return (char_u *)"lgrepadd"; - default: return NULL; + case CMD_vimgrep: + return (char_u *)"vimgrep"; + case CMD_lvimgrep: + return (char_u *)"lvimgrep"; + case CMD_vimgrepadd: + return (char_u *)"vimgrepadd"; + case CMD_lvimgrepadd: + return (char_u *)"lvimgrepadd"; + case CMD_grep: + return (char_u *)"grep"; + case CMD_lgrep: + return (char_u *)"lgrep"; + case CMD_grepadd: + return (char_u *)"grepadd"; + case CMD_lgrepadd: + return (char_u *)"lgrepadd"; + default: + return NULL; } } @@ -5226,8 +5168,7 @@ static void vgr_display_fname(char_u *fname) } /// Load a dummy buffer to search for a pattern using vimgrep. -static buf_T *vgr_load_dummy_buf(char_u *fname, char_u *dirname_start, - char_u *dirname_now) +static buf_T *vgr_load_dummy_buf(char_u *fname, char_u *dirname_start, char_u *dirname_now) { // Don't do Filetype autocommands to avoid loading syntax and // indent scripts, a great speed improvement. @@ -5249,8 +5190,7 @@ static buf_T *vgr_load_dummy_buf(char_u *fname, char_u *dirname_start, /// Check whether a quickfix/location list is valid. Autocmds may remove or /// change a quickfix list when vimgrep is running. If the list is not found, /// create a new list. -static bool vgr_qflist_valid(win_T *wp, qf_info_T *qi, unsigned qfid, - char_u *title) +static bool vgr_qflist_valid(win_T *wp, qf_info_T *qi, unsigned qfid, char_u *title) { // Verify that the quickfix/location list was not freed by an autocmd if (!qflist_valid(wp, qfid)) { @@ -5274,9 +5214,8 @@ static bool vgr_qflist_valid(win_T *wp, qf_info_T *qi, unsigned qfid, /// Search for a pattern in all the lines in a buffer and add the matching lines /// to a quickfix list. -static bool vgr_match_buflines(qf_list_T *qfl, char_u *fname, buf_T *buf, - regmmatch_T *regmatch, long *tomatch, - int duplicate_name, int flags) +static bool vgr_match_buflines(qf_list_T *qfl, char_u *fname, buf_T *buf, regmmatch_T *regmatch, + long *tomatch, int duplicate_name, int flags) FUNC_ATTR_NONNULL_ARG(1, 3, 4, 5) { bool found_match = false; @@ -5373,27 +5312,27 @@ void ex_vimgrep(exarg_T *eap) { regmmatch_T regmatch; int fcount; - char_u **fnames; - char_u *fname; - char_u *s; - char_u *p; + char_u **fnames; + char_u *fname; + char_u *s; + char_u *p; int fi; - qf_list_T *qfl; + qf_list_T *qfl; win_T *wp = NULL; - buf_T *buf; + buf_T *buf; int duplicate_name = FALSE; int using_dummy; int redraw_for_dummy = FALSE; int found_match; - buf_T *first_match_buf = NULL; + buf_T *first_match_buf = NULL; time_t seconds = 0; aco_save_T aco; int flags = 0; long tomatch; - char_u *dirname_start = NULL; - char_u *dirname_now = NULL; - char_u *target_dir = NULL; - char_u *au_name = NULL; + char_u *dirname_start = NULL; + char_u *dirname_now = NULL; + char_u *target_dir = NULL; + char_u *au_name = NULL; au_name = vgr_get_auname(eap->cmdidx); if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, @@ -5405,10 +5344,11 @@ void ex_vimgrep(exarg_T *eap) qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp); - if (eap->addr_count > 0) + if (eap->addr_count > 0) { tomatch = eap->line2; - else + } else { tomatch = MAXLNUM; + } // Get the search pattern: either white-separated or enclosed in // regmatch.regprog = NULL; @@ -5492,8 +5432,9 @@ void ex_vimgrep(exarg_T *eap) save_qfid = qf_get_curlist(qi)->qf_id; if (buf == NULL) { - if (!got_int) + if (!got_int) { smsg(_("Cannot open file \"%s\""), fname); + } } else { // Try for a match in all lines of the buffer. // For ":1vimgrep" look for first match only. @@ -5502,8 +5443,9 @@ void ex_vimgrep(exarg_T *eap) duplicate_name, flags); if (using_dummy) { - if (found_match && first_match_buf == NULL) + if (found_match && first_match_buf == NULL) { first_match_buf = buf; + } if (duplicate_name) { // Never keep a dummy buffer if there is another buffer // with the same name. @@ -5585,8 +5527,9 @@ void ex_vimgrep(exarg_T *eap) vgr_jump_to_match(qi, eap->forceit, &redraw_for_dummy, first_match_buf, target_dir); } - } else + } else { EMSG2(_(e_nomatch2), s); + } decr_quickfix_busy(); @@ -5624,24 +5567,22 @@ static void restore_start_dir(char_u *dirname_start) xfree(dirname_now); } -// Load file "fname" into a dummy buffer and return the buffer pointer, -// placing the directory resulting from the buffer load into the -// "resulting_dir" pointer. "resulting_dir" must be allocated by the caller -// prior to calling this function. Restores directory to "dirname_start" prior -// to returning, if autocmds or the 'autochdir' option have changed it. -// -// If creating the dummy buffer does not fail, must call unload_dummy_buffer() -// or wipe_dummy_buffer() later! -// -// Returns NULL if it fails. -static buf_T * -load_dummy_buffer ( - char_u *fname, - char_u *dirname_start, // in: old directory - char_u *resulting_dir // out: new directory -) -{ - buf_T *newbuf; +/// Load file "fname" into a dummy buffer and return the buffer pointer, +/// placing the directory resulting from the buffer load into the +/// "resulting_dir" pointer. "resulting_dir" must be allocated by the caller +/// prior to calling this function. Restores directory to "dirname_start" prior +/// to returning, if autocmds or the 'autochdir' option have changed it. +/// +/// If creating the dummy buffer does not fail, must call unload_dummy_buffer() +/// or wipe_dummy_buffer() later! +/// +/// @param dirname_start in: old directory +/// @param resulting_dir out: new directory +/// +/// @return NULL if it fails. +static buf_T *load_dummy_buffer(char_u *fname, char_u *dirname_start, char_u *resulting_dir) +{ + buf_T *newbuf; bufref_T newbufref; bufref_T newbuf_to_wipe; int failed = true; @@ -5807,17 +5748,14 @@ static int get_qfline_items(qfline_T *qfp, list_T *list) || (tv_dict_add_nr(dict, S_LEN("vcol"), (varnumber_T)qfp->qf_viscol) == FAIL) || (tv_dict_add_nr(dict, S_LEN("nr"), (varnumber_T)qfp->qf_nr) == FAIL) - || (tv_dict_add_str( - dict, S_LEN("module"), - (qfp->qf_module == NULL ? "" : (const char *)qfp->qf_module)) + || (tv_dict_add_str(dict, S_LEN("module"), + (qfp->qf_module == NULL ? "" : (const char *)qfp->qf_module)) == FAIL) - || (tv_dict_add_str( - dict, S_LEN("pattern"), - (qfp->qf_pattern == NULL ? "" : (const char *)qfp->qf_pattern)) + || (tv_dict_add_str(dict, S_LEN("pattern"), + (qfp->qf_pattern == NULL ? "" : (const char *)qfp->qf_pattern)) == FAIL) - || (tv_dict_add_str( - dict, S_LEN("text"), - (qfp->qf_text == NULL ? "" : (const char *)qfp->qf_text)) + || (tv_dict_add_str(dict, S_LEN("text"), + (qfp->qf_text == NULL ? "" : (const char *)qfp->qf_text)) == FAIL) || (tv_dict_add_str(dict, S_LEN("type"), (const char *)buf) == FAIL) || (tv_dict_add_nr(dict, S_LEN("valid"), (varnumber_T)qfp->qf_valid) @@ -5834,12 +5772,11 @@ static int get_qfline_items(qfline_T *qfp, list_T *list) /// If qf_idx is -1, use the current list. Otherwise, use the specified list. /// If eidx is not 0, then return only the specified entry. Otherwise return /// all the entries. -int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, int eidx, - list_T *list) +int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, int eidx, list_T *list) { qf_info_T *qi = qi_arg; qf_list_T *qfl; - qfline_T *qfp; + qfline_T *qfp; int i; if (qi == NULL) { @@ -5875,7 +5812,7 @@ int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, int eidx, return get_qfline_items(qfp, list); } } else if (get_qfline_items(qfp, list) == FAIL) { - return FAIL; + return FAIL; } } @@ -6051,10 +5988,7 @@ static int qf_getprop_qfidx(qf_info_T *qi, dict_T *what) } /// Return default values for quickfix list properties in retdict. -static int qf_getprop_defaults(qf_info_T *qi, - int flags, - int locstack, - dict_T *retdict) +static int qf_getprop_defaults(qf_info_T *qi, int flags, int locstack, dict_T *retdict) { int status = OK; @@ -6099,15 +6033,14 @@ static int qf_getprop_defaults(qf_info_T *qi, /// Return the quickfix list title as 'title' in retdict static int qf_getprop_title(qf_list_T *qfl, dict_T *retdict) { - return tv_dict_add_str(retdict, S_LEN("title"), - (const char *)qfl->qf_title); + return tv_dict_add_str(retdict, S_LEN("title"), + (const char *)qfl->qf_title); } // Returns the identifier of the window used to display files from a location // list. If there is no associated window, then returns 0. Useful only when // called from a location list window. -static int qf_getprop_filewinid(const win_T *wp, const qf_info_T *qi, - dict_T *retdict) +static int qf_getprop_filewinid(const win_T *wp, const qf_info_T *qi, dict_T *retdict) FUNC_ATTR_NONNULL_ARG(3) { handle_T winid = 0; @@ -6124,8 +6057,7 @@ static int qf_getprop_filewinid(const win_T *wp, const qf_info_T *qi, /// Return the quickfix list items/entries as 'items' in retdict. /// If eidx is not 0, then return the item at the specified index. -static int qf_getprop_items(qf_info_T *qi, int qf_idx, int eidx, - dict_T *retdict) +static int qf_getprop_items(qf_info_T *qi, int qf_idx, int eidx, dict_T *retdict) { list_T *l = tv_list_alloc(kListLenMayKnow); get_errorlist(qi, NULL, qf_idx, eidx, l); @@ -6284,11 +6216,8 @@ static int qf_setprop_qftf(qf_list_T *qfl, dictitem_T *di) /// Add a new quickfix entry to list at 'qf_idx' in the stack 'qi' from the /// items in the dict 'd'. If it is a valid error entry, then set 'valid_entry' /// to true. -static int qf_add_entry_from_dict( - qf_list_T *qfl, - const dict_T *d, - bool first_entry, - bool *valid_entry) +static int qf_add_entry_from_dict(qf_list_T *qfl, const dict_T *d, bool first_entry, + bool *valid_entry) FUNC_ATTR_NONNULL_ALL { static bool did_bufnr_emsg; @@ -6364,8 +6293,7 @@ static int qf_add_entry_from_dict( /// Add list of entries to quickfix/location list. Each list entry is /// a dictionary with item information. -static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list, - char_u *title, int action) +static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list, char_u *title, int action) { qf_list_T *qfl = qf_get_list(qi, qf_idx); qfline_T *old_last = NULL; @@ -6428,11 +6356,7 @@ static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list, } /// Get the quickfix list index from 'nr' or 'id' -static int qf_setprop_get_qfidx( - const qf_info_T *qi, - const dict_T *what, - int action, - bool *newlist) +static int qf_setprop_get_qfidx(const qf_info_T *qi, const dict_T *what, int action, bool *newlist) FUNC_ATTR_NONNULL_ALL { dictitem_T *di; @@ -6483,8 +6407,7 @@ static int qf_setprop_get_qfidx( } // Set the quickfix list title. -static int qf_setprop_title(qf_info_T *qi, int qf_idx, const dict_T *what, - const dictitem_T *di) +static int qf_setprop_title(qf_info_T *qi, int qf_idx, const dict_T *what, const dictitem_T *di) FUNC_ATTR_NONNULL_ALL { qf_list_T *qfl = qf_get_list(qi, qf_idx); @@ -6502,8 +6425,7 @@ static int qf_setprop_title(qf_info_T *qi, int qf_idx, const dict_T *what, } // Set quickfix list items/entries. -static int qf_setprop_items(qf_info_T *qi, int qf_idx, dictitem_T *di, - int action) +static int qf_setprop_items(qf_info_T *qi, int qf_idx, dictitem_T *di, int action) FUNC_ATTR_NONNULL_ALL { if (di->di_tv.v_type != VAR_LIST) { @@ -6520,17 +6442,13 @@ static int qf_setprop_items(qf_info_T *qi, int qf_idx, dictitem_T *di, } // Set quickfix list items/entries from a list of lines. -static int qf_setprop_items_from_lines( - qf_info_T *qi, - int qf_idx, - const dict_T *what, - dictitem_T *di, - int action) +static int qf_setprop_items_from_lines(qf_info_T *qi, int qf_idx, const dict_T *what, + dictitem_T *di, int action) FUNC_ATTR_NONNULL_ALL { char_u *errorformat = p_efm; dictitem_T *efm_di; - int retval = FAIL; + int retval = FAIL; // Use the user supplied errorformat settings (if present) if ((efm_di = tv_dict_find(what, S_LEN("efm"))) != NULL) { @@ -6570,11 +6488,10 @@ static int qf_setprop_context(qf_list_T *qfl, dictitem_T *di) } // Set the current index in the specified quickfix list -static int qf_setprop_curidx(qf_info_T *qi, qf_list_T *qfl, - const dictitem_T *di) +static int qf_setprop_curidx(qf_info_T *qi, qf_list_T *qfl, const dictitem_T *di) FUNC_ATTR_NONNULL_ALL { - int newidx; + int newidx; // If the specified index is '$', then use the last entry if (di->di_tv.v_type == VAR_STRING @@ -6615,13 +6532,12 @@ static int qf_setprop_curidx(qf_info_T *qi, qf_list_T *qfl, /// Set quickfix/location list properties (title, items, context). /// Also used to add items from parsing a list of lines. /// Used by the setqflist() and setloclist() Vim script functions. -static int qf_set_properties(qf_info_T *qi, const dict_T *what, int action, - char_u *title) +static int qf_set_properties(qf_info_T *qi, const dict_T *what, int action, char_u *title) FUNC_ATTR_NONNULL_ALL { qf_list_T *qfl; dictitem_T *di; - int retval = FAIL; + int retval = FAIL; bool newlist = action == ' ' || qf_stack_empty(qi); int qf_idx = qf_setprop_get_qfidx(qi, what, action, &newlist); if (qf_idx == INVALID_QFIDX) { // List not found @@ -6727,8 +6643,7 @@ static void qf_free_stack(win_T *wp, qf_info_T *qi) // of dictionaries. "title" will be copied to w:quickfix_title // "action" is 'a' for add, 'r' for replace. Otherwise create a new list. // When "what" is not NULL then only set some properties. -int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, - dict_T *what) +int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, dict_T *what) { qf_info_T *qi = &ql_info; int retval = OK; @@ -6813,32 +6728,37 @@ bool set_ref_in_quickfix(int copyID) } /// Return the autocmd name for the :cbuffer Ex commands -static char_u * cbuffer_get_auname(cmdidx_T cmdidx) +static char_u *cbuffer_get_auname(cmdidx_T cmdidx) { switch (cmdidx) { - case CMD_cbuffer: return (char_u *)"cbuffer"; - case CMD_cgetbuffer: return (char_u *)"cgetbuffer"; - case CMD_caddbuffer: return (char_u *)"caddbuffer"; - case CMD_lbuffer: return (char_u *)"lbuffer"; - case CMD_lgetbuffer: return (char_u *)"lgetbuffer"; - case CMD_laddbuffer: return (char_u *)"laddbuffer"; - default: return NULL; + case CMD_cbuffer: + return (char_u *)"cbuffer"; + case CMD_cgetbuffer: + return (char_u *)"cgetbuffer"; + case CMD_caddbuffer: + return (char_u *)"caddbuffer"; + case CMD_lbuffer: + return (char_u *)"lbuffer"; + case CMD_lgetbuffer: + return (char_u *)"lgetbuffer"; + case CMD_laddbuffer: + return (char_u *)"laddbuffer"; + default: + return NULL; } } /// Process and validate the arguments passed to the :cbuffer, :caddbuffer, /// :cgetbuffer, :lbuffer, :laddbuffer, :lgetbuffer Ex commands. -static int cbuffer_process_args(exarg_T *eap, - buf_T **bufp, - linenr_T *line1, - linenr_T *line2) +static int cbuffer_process_args(exarg_T *eap, buf_T **bufp, linenr_T *line1, linenr_T *line2) { buf_T *buf = NULL; - if (*eap->arg == NUL) + if (*eap->arg == NUL) { buf = curbuf; - else if (*skipwhite(skipdigits(eap->arg)) == NUL) + } else if (*skipwhite(skipdigits(eap->arg)) == NUL) { buf = buflist_findnr(atoi((char *)eap->arg)); + } if (buf == NULL) { EMSG(_(e_invarg)); @@ -6944,16 +6864,23 @@ void ex_cbuffer(exarg_T *eap) } /// Return the autocmd name for the :cexpr Ex commands. -static char_u * cexpr_get_auname(cmdidx_T cmdidx) +static char_u *cexpr_get_auname(cmdidx_T cmdidx) { switch (cmdidx) { - case CMD_cexpr: return (char_u *)"cexpr"; - case CMD_cgetexpr: return (char_u *)"cgetexpr"; - case CMD_caddexpr: return (char_u *)"caddexpr"; - case CMD_lexpr: return (char_u *)"lexpr"; - case CMD_lgetexpr: return (char_u *)"lgetexpr"; - case CMD_laddexpr: return (char_u *)"laddexpr"; - default: return NULL; + case CMD_cexpr: + return (char_u *)"cexpr"; + case CMD_cgetexpr: + return (char_u *)"cgetexpr"; + case CMD_caddexpr: + return (char_u *)"caddexpr"; + case CMD_lexpr: + return (char_u *)"lexpr"; + case CMD_lgetexpr: + return (char_u *)"lgetexpr"; + case CMD_laddexpr: + return (char_u *)"laddexpr"; + default: + return NULL; } } @@ -7047,10 +6974,7 @@ static qf_info_T *hgr_get_ll(bool *new_ll) } // Search for a pattern in a help file. -static void hgr_search_file( - qf_list_T *qfl, - char_u *fname, - regmatch_T *p_regmatch) +static void hgr_search_file(qf_list_T *qfl, char_u *fname, regmatch_T *p_regmatch) FUNC_ATTR_NONNULL_ARG(1, 3) { FILE *const fd = os_fopen((char *)fname, "r"); @@ -7105,11 +7029,8 @@ static void hgr_search_file( // Search for a pattern in all the help files in the doc directory under // the given directory. -static void hgr_search_files_in_dir( - qf_list_T *qfl, - char_u *dirname, - regmatch_T *p_regmatch, - const char_u *lang) +static void hgr_search_files_in_dir(qf_list_T *qfl, char_u *dirname, regmatch_T *p_regmatch, + const char_u *lang) FUNC_ATTR_NONNULL_ARG(1, 2, 3) { int fcount; @@ -7141,8 +7062,7 @@ static void hgr_search_files_in_dir( // and add the matches to a quickfix list. // 'lang' is the language specifier. If supplied, then only matches in the // specified language are found. -static void hgr_search_in_rtp(qf_list_T *qfl, regmatch_T *p_regmatch, - const char_u *lang) +static void hgr_search_in_rtp(qf_list_T *qfl, regmatch_T *p_regmatch, const char_u *lang) FUNC_ATTR_NONNULL_ARG(1, 2) { // Go through all directories in 'runtimepath' @@ -7162,9 +7082,12 @@ void ex_helpgrep(exarg_T *eap) char_u *au_name = NULL; switch (eap->cmdidx) { - case CMD_helpgrep: au_name = (char_u *)"helpgrep"; break; - case CMD_lhelpgrep: au_name = (char_u *)"lhelpgrep"; break; - default: break; + case CMD_helpgrep: + au_name = (char_u *)"helpgrep"; break; + case CMD_lhelpgrep: + au_name = (char_u *)"lhelpgrep"; break; + default: + break; } if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, curbuf->b_fname, true, curbuf)) { diff --git a/src/nvim/rbuffer.c b/src/nvim/rbuffer.c index df9394fbb2..4ac50095b3 100644 --- a/src/nvim/rbuffer.c +++ b/src/nvim/rbuffer.c @@ -6,8 +6,8 @@ #include <string.h> #include "nvim/memory.h" -#include "nvim/vim.h" #include "nvim/rbuffer.h" +#include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "rbuffer.c.generated.h" @@ -144,7 +144,7 @@ void rbuffer_consumed(RBuffer *buf, size_t count) buf->read_ptr += count; if (buf->read_ptr >= buf->end_ptr) { - buf->read_ptr -= rbuffer_capacity(buf); + buf->read_ptr -= rbuffer_capacity(buf); } bool was_full = buf->size == rbuffer_capacity(buf); diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index d4191cff6b..6bed22fbb0 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -5,21 +5,24 @@ /// /// Management of runtime files (including packages) -#include "nvim/vim.h" #include "nvim/ascii.h" +#include "nvim/api/private/helpers.h" #include "nvim/charset.h" #include "nvim/eval.h" -#include "nvim/option.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds2.h" #include "nvim/misc1.h" +#include "nvim/option.h" #include "nvim/os/os.h" #include "nvim/runtime.h" +#include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "runtime.c.generated.h" #endif +static bool search_path_valid = false; +static RuntimeSearchPath runtime_search_path; /// ":runtime [what] {name}" void ex_runtime(exarg_T *eap) @@ -60,12 +63,11 @@ static void source_callback(char_u *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_u *name, int flags, - DoInRuntimepathCB callback, void *cookie) +int do_in_path(char_u *path, char_u *name, int flags, DoInRuntimepathCB callback, void *cookie) { - char_u *tail; + char_u *tail; int num_files; - char_u **files; + char_u **files; int i; bool did_one = false; @@ -90,8 +92,7 @@ int do_in_path(char_u *path, char_u *name, int flags, // Skip after or non-after directories. if (flags & (DIP_NOAFTER | DIP_AFTER)) { - bool is_after = buflen >= 5 - && STRCMP(buf + buflen - 5, "after") == 0; + bool is_after = path_is_after(buf, buflen); if ((is_after && (flags & DIP_NOAFTER)) || (!is_after && (flags & DIP_AFTER))) { @@ -156,6 +157,98 @@ int do_in_path(char_u *path, char_u *name, int flags, return did_one ? OK : FAIL; } +/// Find the file "name" in all directories in "path" and invoke +/// "callback(fname, cookie)". +/// "name" can contain wildcards. +/// When "flags" has DIP_ALL: source all files, otherwise only the first one. +/// When "flags" has DIP_DIR: find directories instead of files. +/// 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) +{ + validate_search_path(); + char_u *tail; + int num_files; + char_u **files; + int i; + bool did_one = false; + + char_u buf[MAXPATHL]; + + if (p_verbose > 10 && name != NULL) { + verbose_enter(); + smsg(_("Searching for \"%s\" in runtime path"), (char *)name); + verbose_leave(); + } + + // Loop over all entries in 'runtimepath'. + for (size_t j = 0; j < kv_size(runtime_search_path); j++) { + SearchPathItem item = kv_A(runtime_search_path, j); + size_t buflen = strlen(item.path); + + // Skip after or non-after directories. + if (flags & (DIP_NOAFTER | DIP_AFTER)) { + if ((item.after && (flags & DIP_NOAFTER)) + || (!item.after && (flags & DIP_AFTER))) { + continue; + } + } + + if (name == NULL) { + (*callback)((char_u *)item.path, cookie); + did_one = true; + } else if (buflen + STRLEN(name) + 2 < MAXPATHL) { + STRCPY(buf, item.path); + add_pathsep((char *)buf); + tail = buf + STRLEN(buf); + + // Loop over all patterns in "name" + char_u *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, tail, (size_t)(MAXPATHL - (tail - buf)), + "\t "); + + if (p_verbose > 10) { + verbose_enter(); + smsg(_("Searching for \"%s\""), buf); + verbose_leave(); + } + + int ew_flags = ((flags & DIP_DIR) ? EW_DIR : EW_FILE) + | (flags & DIP_DIRFILE) ? (EW_DIR|EW_FILE) : 0; + + // Expand wildcards, invoke the callback for each match. + char_u *(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); + did_one = true; + if (!(flags & DIP_ALL)) { + break; + } + } + FreeWild(num_files, files); + } + } + } + } + + if (!did_one && name != NULL) { + if (flags & DIP_ERR) { + EMSG3(_(e_dirnotf), "runtime path", name); + } else if (p_verbose > 0) { + verbose_enter(); + smsg(_("not found in runtime path: \"%s\""), name); + verbose_leave(); + } + } + + + return did_one ? OK : FAIL; +} /// Find "name" in "path". When found, invoke the callback function for /// it: callback(fname, "cookie") /// When "flags" has DIP_ALL repeat for all matches, otherwise only the first @@ -164,17 +257,10 @@ int do_in_path(char_u *path, char_u *name, int flags, /// 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_u *path, char_u *name, int flags, DoInRuntimepathCB callback, + void *cookie) { int done = FAIL; - if (!(flags & (DIP_NOAFTER | DIP_AFTER))) { - done = do_in_path_and_pp(path, name, flags | DIP_NOAFTER, callback, cookie); - if (done == OK && !(flags & DIP_ALL)) { - return done; - } - flags |= DIP_AFTER; - } if ((flags & DIP_NORTP) == 0) { done |= do_in_path(path, (name && !*name) ? NULL : name, flags, callback, cookie); @@ -228,10 +314,152 @@ int do_in_path_and_pp(char_u *path, char_u *name, int flags, return done; } +static void push_path(RuntimeSearchPath *search_path, char *entry, bool after) +{ + kv_push(*search_path, ((SearchPathItem){ entry, after })); +} + +static void expand_pack_entry(RuntimeSearchPath *search_path, CharVec *after_path, + char_u *pack_entry) +{ + static char_u buf[MAXPATHL], buf2[MAXPATHL]; + char *start_dir = "/pack/*/start/*/"; // NOLINT + if (STRLEN(pack_entry) + STRLEN(start_dir) + 1 < MAXPATHL) { + xstrlcpy((char *)buf, (char *)pack_entry, MAXPATHL); + xstrlcpy((char *)buf2, (char *)pack_entry, MAXPATHL); + xstrlcat((char *)buf, start_dir, sizeof buf); + xstrlcat((char *)buf2, "/start/*/", sizeof buf); // NOLINT + int num_files; + char_u **files; + + char_u *(pat[]) = { buf, buf2 }; + if (gen_expand_wildcards(2, pat, &num_files, &files, EW_DIR) == OK) { + for (int i = 0; i < num_files; i++) { + push_path(search_path, xstrdup((char *)files[i]), false); + size_t after_size = STRLEN(files[i])+6; + char *after = xmallocz(after_size); + xstrlcpy(after, (char *)files[i], after_size); + xstrlcat(after, "after/", after_size); + if (os_isdir((char_u *)after)) { + push_path(search_path, after, true); + } else { + xfree(after); + } + } + FreeWild(num_files, files); + } + } +} + +static bool path_is_after(char_u *buf, size_t buflen) +{ + // NOTE: we only consider dirs exactly matching "after" to be an AFTER dir. + // vim8 considers all dirs like "foo/bar_after", "Xafter" etc, as an + // "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; +} + +RuntimeSearchPath build_runtime_search_path(void) +{ + kvec_t(String) pack_entries = KV_INITIAL_VALUE; + Map(String, handle_T) pack_used = MAP_INIT; + // TODO(bfredl): add a set of existing rtp entries to not duplicate those + 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; ) { + char *cur_entry = entry; + copy_option_part((char_u **)&entry, buf, MAXPATHL, ","); + + String the_entry = { .data = cur_entry, .size = STRLEN(buf) }; + + kv_push(pack_entries, the_entry); + map_put(String, handle_T)(&pack_used, the_entry, 0); + } + + + char *rtp_entry; + for (rtp_entry = (char *)p_rtp; *rtp_entry != NUL; ) { + char *cur_entry = rtp_entry; + copy_option_part((char_u **)&rtp_entry, buf, MAXPATHL, ","); + size_t buflen = STRLEN(buf); + + if (path_is_after(buf, buflen)) { + rtp_entry = cur_entry; + break; + } + + push_path(&search_path, xstrdup((char *)buf), false); + + handle_T *h = map_ref(String, handle_T)(&pack_used, cstr_as_string((char *)buf), false); + if (h) { + (*h)++; + expand_pack_entry(&search_path, &after_path, buf); + } + } + + for (size_t i = 0; i < kv_size(pack_entries); i++) { + handle_T h = map_get(String, handle_T)(&pack_used, cstr_as_string((char *)buf)); + if (h == 0) { + expand_pack_entry(&search_path, &after_path, (char_u *)kv_A(pack_entries, i).data); + } + } + + // "after" packages + for (size_t i = 0; i < kv_size(after_path); i++) { + push_path(&search_path, kv_A(after_path, i), true); + } + + // "after" dirs in rtp + for (; *rtp_entry != NUL;) { + copy_option_part((char_u **)&rtp_entry, buf, MAXPATHL, ","); + push_path(&search_path, xstrdup((char *)buf), path_is_after(buf, STRLEN(buf))); + } + + // strings are not owned + kv_destroy(pack_entries); + map_destroy(String, handle_T)(&pack_used); + + return search_path; +} + +void invalidate_search_path(void) +{ + search_path_valid = false; +} + +void validate_search_path(void) +{ + if (!search_path_valid) { + for (size_t j = 0; j < kv_size(runtime_search_path); j++) { + SearchPathItem item = kv_A(runtime_search_path, j); + xfree(item.path); + } + kv_destroy(runtime_search_path); + runtime_search_path = build_runtime_search_path(); + search_path_valid = true; + } +} + + + /// Just like do_in_path_and_pp(), using 'runtimepath' for "path". int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback, void *cookie) { - return do_in_path_and_pp(p_rtp, name, flags | DIP_START, callback, cookie); + int success = FAIL; + if (!(flags & DIP_NORTP)) { + 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, name, flags, callback, cookie); + } + return success; } /// Source the file "name" from all directories in 'runtimepath'. @@ -241,8 +469,7 @@ int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback, void /// return FAIL when no file could be sourced, OK otherwise. int source_runtime(char_u *name, int flags) { - flags |= (flags & DIP_NORTP) ? 0 : DIP_START; - return source_in_path(p_rtp, name, flags); + return do_in_runtimepath(name, flags, source_callback, NULL); } /// Just like source_runtime(), but use "path" instead of 'runtimepath'. @@ -564,8 +791,7 @@ static char *strcpy_comma_escaped(char *dest, const char *src, const size_t len) /// (common_suf is present after each new item, single_suf is present /// after half of the new items) and with commas after each item, commas /// inside the values are escaped. -static inline size_t compute_double_env_sep_len(const char *const val, - const size_t common_suf_len, +static inline size_t compute_double_env_sep_len(const char *const val, const size_t common_suf_len, const size_t single_suf_len) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { @@ -608,9 +834,8 @@ static inline size_t compute_double_env_sep_len(const char *const val, /// Otherwise in reverse. /// /// @return (dest + appended_characters_length) -static inline char *add_env_sep_dirs(char *dest, const char *const val, - const char *const suf1, const size_t len1, - const char *const suf2, const size_t len2, +static inline char *add_env_sep_dirs(char *dest, const char *const val, const char *const suf1, + const size_t len1, const char *const suf2, const size_t len2, const bool forward) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ARG(1) { @@ -669,9 +894,8 @@ static inline char *add_env_sep_dirs(char *dest, const char *const val, /// Otherwise in reverse. /// /// @return (dest + appended_characters_length) -static inline char *add_dir(char *dest, const char *const dir, - const size_t dir_len, const XDGVarType type, - const char *const suf1, const size_t len1, +static inline char *add_dir(char *dest, const char *const dir, const size_t dir_len, + const XDGVarType type, const char *const suf1, const size_t len1, const char *const suf2, const size_t len2) FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT { diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h index b40c2b670e..db31ae4e1e 100644 --- a/src/nvim/runtime.h +++ b/src/nvim/runtime.h @@ -7,10 +7,30 @@ typedef void (*DoInRuntimepathCB)(char_u *, void *); +typedef struct { + char *path; + bool after; +} SearchPathItem; + +typedef kvec_t(SearchPathItem) RuntimeSearchPath; +typedef kvec_t(char *) CharVec; + // last argument for do_source() #define DOSO_NONE 0 #define DOSO_VIMRC 1 // loading vimrc file +// Used for flags in do_in_path() +#define DIP_ALL 0x01 // all matches, not just the first one +#define DIP_DIR 0x02 // find directories instead of files +#define DIP_ERR 0x04 // give an error message when none found +#define DIP_START 0x08 // also use "start" directory in 'packpath' +#define DIP_OPT 0x10 // also use "opt" directory in 'packpath' +#define DIP_NORTP 0x20 // do not use 'runtimepath' +#define DIP_NOAFTER 0x40 // skip "after" directories +#define DIP_AFTER 0x80 // only use "after" directories +#define DIP_LUA 0x100 // also use ".lua" files +#define DIP_DIRFILE 0x200 // find both files and directories + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "runtime.h.generated.h" diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 79e960fe8b..057e800ee2 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -1003,8 +1003,7 @@ static void win_update(win_T *wp, Providers *providers) i = plines_m_win(wp, wp->w_topline, wp->w_lines[0].wl_lnum - 1); // insert extra lines for previously invisible filler lines if (wp->w_lines[0].wl_lnum != wp->w_topline) { - i += diff_check_fill(wp, wp->w_lines[0].wl_lnum) - - wp->w_old_topfill; + i += win_get_fill(wp, wp->w_lines[0].wl_lnum) - wp->w_old_topfill; } if (i != 0 && i < wp->w_grid.Rows - 2) { // less than a screen off // Try to insert the correct number of lines. @@ -1067,7 +1066,7 @@ static void win_update(win_T *wp, Providers *providers) if (wp->w_lines[0].wl_lnum == wp->w_topline) { row += wp->w_old_topfill; } else { - row += diff_check_fill(wp, wp->w_topline); + row += win_get_fill(wp, wp->w_topline); } // ... but don't delete new filler lines. row -= wp->w_topfill; @@ -1101,12 +1100,12 @@ static void win_update(win_T *wp, Providers *providers) break; } } - /* Correct the first entry for filler lines at the top - * when it won't get updated below. */ - if (wp->w_p_diff && bot_start > 0) { - wp->w_lines[0].wl_size = - plines_win_nofill(wp, wp->w_topline, true) - + wp->w_topfill; + + // Correct the first entry for filler lines at the top + // when it won't get updated below. + if (win_may_fill(wp) && bot_start > 0) { + wp->w_lines[0].wl_size = (plines_win_nofill(wp, wp->w_topline, true) + + wp->w_topfill); } } } @@ -1564,7 +1563,7 @@ static void win_update(win_T *wp, Providers *providers) && lnum > wp->w_topline && !(dy_flags & (DY_LASTLINE | DY_TRUNCATE)) && srow + wp->w_lines[idx].wl_size > wp->w_grid.Rows - && diff_check_fill(wp, lnum) == 0) { + && win_get_fill(wp, lnum) == 0) { // This line is not going to fit. Don't draw anything here, // will draw "@ " lines below. row = wp->w_grid.Rows + 1; @@ -1664,7 +1663,7 @@ static void win_update(win_T *wp, Providers *providers) * Don't overwrite it, it can be edited. */ wp->w_botline = lnum + 1; - } else if (diff_check_fill(wp, lnum) >= wp->w_grid.Rows - srow) { + } else if (win_get_fill(wp, lnum) >= wp->w_grid.Rows - srow) { // Window ends in filler lines. wp->w_botline = lnum; wp->w_filler_rows = wp->w_grid.Rows - srow; @@ -1691,7 +1690,7 @@ static void win_update(win_T *wp, Providers *providers) } else { if (eof) { // we hit the end of the file wp->w_botline = buf->b_ml.ml_line_count + 1; - j = diff_check_fill(wp, wp->w_botline); + j = win_get_fill(wp, wp->w_botline); if (j > 0 && !wp->w_botfill) { // Display filler text below last line. win_line() will check // for ml_line_count+1 and only draw filler lines @@ -1866,7 +1865,7 @@ static int compute_foldcolumn(win_T *wp, int col) /// Put a single char from an UTF-8 buffer into a line buffer. /// /// Handles composing chars and arabic shaping state. -static int line_putchar(LineState *s, schar_T *dest, int maxcells, bool rl) +static int line_putchar(buf_T *buf, LineState *s, schar_T *dest, int maxcells, bool rl, int vcol) { const char_u *p = (char_u *)s->p; int cells = utf_ptr2cells(p); @@ -1876,7 +1875,13 @@ static int line_putchar(LineState *s, schar_T *dest, int maxcells, bool rl) return -1; } u8c = utfc_ptr2char(p, u8cc); - if (*p < 0x80 && u8cc[0] == 0) { + 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++) { + schar_from_ascii(dest[c], ' '); + } + goto done; + } else if (*p < 0x80 && u8cc[0] == 0) { schar_from_ascii(dest[0], *p); s->prev_c = u8c; } else { @@ -1909,6 +1914,7 @@ static int line_putchar(LineState *s, schar_T *dest, int maxcells, bool rl) if (cells > 1) { dest[1][0] = 0; } +done: s->p += c_len; return cells; } @@ -2366,8 +2372,11 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc filler_lines = 0; area_highlighting = true; } + int virtual_lines = decor_virtual_lines(wp, lnum); + filler_lines += virtual_lines; if (lnum == wp->w_topline) { filler_lines = wp->w_topfill; + virtual_lines = MIN(virtual_lines, filler_lines); } filler_todo = filler_lines; @@ -2895,7 +2904,18 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc if (draw_state == WL_SBR - 1 && n_extra == 0) { draw_state = WL_SBR; - if (filler_todo > 0) { + if (filler_todo > filler_lines - virtual_lines) { + // TODO(bfredl): check this doesn't inhibit TUI-style + // clear-to-end-of-line. + c_extra = ' '; + c_final = NUL; + if (wp->w_p_rl) { + n_extra = col + 1; + } else { + n_extra = grid->Columns - col; + } + char_attr = 0; + } else if (filler_todo > 0) { // draw "deleted" diff line(s) if (char2cells(wp->w_p_fcs_chars.diff) > 1) { c_extra = '-'; @@ -3667,8 +3687,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc n_extra = tab_len; } else { char_u *p; - int i; - int saved_nextra = n_extra; + int i; + int saved_nextra = n_extra; if (vcol_off > 0) { // there are characters to conceal @@ -4402,7 +4422,19 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc && !wp->w_p_rl; // Not right-to-left. int draw_col = col - boguscols; - draw_virt_text(buf, win_col_offset, &draw_col, grid->Columns); + if (filler_todo > 0) { + int index = filler_todo - (filler_lines - virtual_lines); + if (index > 0) { + int fpos = kv_size(buf->b_virt_lines) - index; + assert(fpos >= 0); + int offset = buf->b_virt_line_leftcol ? 0 : win_col_offset; + draw_virt_text_item(buf, offset, kv_A(buf->b_virt_lines, fpos), + kHlModeReplace, grid->Columns, offset); + } + } else { + draw_virt_text(buf, win_col_offset, &draw_col, grid->Columns); + } + grid_put_linebuf(grid, row, 0, draw_col, grid->Columns, wp->w_p_rl, wp, wp->w_hl_attr_normal, wrap); if (wrap) { @@ -4485,67 +4517,80 @@ void draw_virt_text(buf_T *buf, int col_off, int *end_col, int max_col) bool do_eol = state->eol_col > -1; for (size_t i = 0; i < kv_size(state->active); i++) { DecorRange *item = &kv_A(state->active, i); - if (item->start_row == state->row && kv_size(item->decor.virt_text)) { - if (item->win_col == -1) { - if (item->decor.virt_text_pos == kVTRightAlign) { - right_pos -= item->decor.virt_text_width; - item->win_col = right_pos; - } else if (item->decor.virt_text_pos == kVTEndOfLine && do_eol) { - item->win_col = state->eol_col; - state->eol_col += item->decor.virt_text_width; - } else if (item->decor.virt_text_pos == kVTWinCol) { - item->win_col = MAX(item->decor.col+col_off, 0); - } - } - if (item->win_col < 0) { - continue; - } - VirtText vt = item->decor.virt_text; - HlMode hl_mode = item->decor.hl_mode; - LineState s = LINE_STATE(""); - int virt_attr = 0; - int col = item->win_col; - size_t virt_pos = 0; - item->win_col = -2; // deactivate - - while (col < max_col) { - if (!*s.p) { - if (virt_pos >= kv_size(vt)) { - break; - } - virt_attr = 0; - do { - s.p = kv_A(vt, virt_pos).text; - int hl_id = kv_A(vt, virt_pos).hl_id; - virt_attr = hl_combine_attr(virt_attr, - hl_id > 0 ? syn_id2attr(hl_id) : 0); - virt_pos++; - } while (!s.p && virt_pos < kv_size(vt)); - if (!s.p) { - break; - } - } - int attr; - bool through = false; - if (hl_mode == kHlModeCombine) { - attr = hl_combine_attr(linebuf_attr[col], virt_attr); - } else if (hl_mode == kHlModeBlend) { - through = (*s.p == ' '); - attr = hl_blend_attrs(linebuf_attr[col], virt_attr, &through); - } else { - attr = virt_attr; - } - schar_T dummy[2]; - int cells = line_putchar(&s, through ? dummy : &linebuf_char[col], - max_col-col, false); - linebuf_attr[col++] = attr; - if (cells > 1) { - linebuf_attr[col++] = attr; - } + if (!(item->start_row == state->row && kv_size(item->decor.virt_text))) { + continue; + } + if (item->win_col == -1) { + if (item->decor.virt_text_pos == kVTRightAlign) { + right_pos -= item->decor.virt_text_width; + item->win_col = right_pos; + } else if (item->decor.virt_text_pos == kVTEndOfLine && do_eol) { + item->win_col = state->eol_col; + } else if (item->decor.virt_text_pos == kVTWinCol) { + item->win_col = MAX(item->decor.col+col_off, 0); + } + } + if (item->win_col < 0) { + continue; + } + + int col = draw_virt_text_item(buf, item->win_col, item->decor.virt_text, + item->decor.hl_mode, max_col, item->win_col-col_off); + item->win_col = -2; // deactivate + if (item->decor.virt_text_pos == kVTEndOfLine && do_eol) { + state->eol_col = col+1; + } + + *end_col = MAX(*end_col, col); + } +} + +static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, + int max_col, int vcol) +{ + LineState s = LINE_STATE(""); + int virt_attr = 0; + size_t virt_pos = 0; + + while (col < max_col) { + if (!*s.p) { + if (virt_pos >= kv_size(vt)) { + break; + } + virt_attr = 0; + do { + s.p = kv_A(vt, virt_pos).text; + int hl_id = kv_A(vt, virt_pos).hl_id; + virt_attr = hl_combine_attr(virt_attr, + hl_id > 0 ? syn_id2attr(hl_id) : 0); + virt_pos++; + } while (!s.p && virt_pos < kv_size(vt)); + if (!s.p) { + break; } - *end_col = MAX(*end_col, col); } + int attr; + bool through = false; + if (hl_mode == kHlModeCombine) { + attr = hl_combine_attr(linebuf_attr[col], virt_attr); + } else if (hl_mode == kHlModeBlend) { + through = (*s.p == ' '); + attr = hl_blend_attrs(linebuf_attr[col], virt_attr, &through); + } else { + attr = virt_attr; + } + schar_T dummy[2]; + int cells = line_putchar(buf, &s, through ? dummy : &linebuf_char[col], + max_col-col, false, vcol); + // if we failed to emit a char, we still need to advance + cells = MAX(cells, 1); + + for (int c = 0; c < cells; c++) { + linebuf_attr[col++] = attr; + } + vcol += cells; } + return col; } /// Determine if dedicated window grid should be used or the default_grid @@ -5489,7 +5534,7 @@ static void win_redr_custom(win_T *wp, bool draw_ruler) ewp->w_p_crb = p_crb_save; // Make all characters printable. - p = (char_u *)transstr((const char *)buf); + p = (char_u *)transstr((const char *)buf, true); len = STRLCPY(buf, p, sizeof(buf)); len = (size_t)len < sizeof(buf) ? len : (int)sizeof(buf) - 1; xfree(p); diff --git a/src/nvim/search.c b/src/nvim/search.c index 4be2402f1d..3d30932d69 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -1046,8 +1046,8 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count, char_u *strcopy = NULL; char_u *ps; char_u *msgbuf = NULL; - size_t len; - bool has_offset = false; + size_t len; + bool has_offset = false; /* * A line offset is not remembered, this is vi compatible. @@ -1182,8 +1182,8 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count, if ((options & SEARCH_ECHO) && messaging() && !msg_silent && (!cmd_silent || !shortmess(SHM_SEARCHCOUNT))) { char_u *trunc; - char_u off_buf[40]; - size_t off_len = 0; + char_u off_buf[40]; + size_t off_len = 0; // Compute msg_row early. msg_start(); @@ -2459,7 +2459,7 @@ int findsent(Direction dir, long count) { pos_T pos, tpos; int c; - int (*func)(pos_T *); + int (*func)(pos_T *); bool noskip = false; // do not skip blanks pos = curwin->w_cursor; @@ -4474,7 +4474,7 @@ static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, bool sh update_search_stat(dirc, pos, cursor_pos, &stat, recompute, maxcount, timeout); if (stat.cur > 0) { - char t[SEARCH_STAT_BUF_LEN]; + char t[SEARCH_STAT_BUF_LEN]; if (curwin->w_p_rl && *curwin->w_p_rlc == 's') { if (stat.incomplete == 1) { @@ -4534,19 +4534,19 @@ static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, bool sh static void update_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, searchstat_T *stat, bool recompute, int maxcount, long timeout) { - int save_ws = p_ws; - bool wraparound = false; - pos_T p = (*pos); - static pos_T lastpos = { 0, 0, 0 }; - static int cur = 0; - static int cnt = 0; - static bool exact_match = false; - static int incomplete = 0; - static int last_maxcount = SEARCH_STAT_DEF_MAX_COUNT; - static int chgtick = 0; + int save_ws = p_ws; + bool wraparound = false; + pos_T p = (*pos); + static pos_T lastpos = { 0, 0, 0 }; + static int cur = 0; + static int cnt = 0; + static bool exact_match = false; + static int incomplete = 0; + static int last_maxcount = SEARCH_STAT_DEF_MAX_COUNT; + static int chgtick = 0; static char_u *lastpat = NULL; static buf_T *lbuf = NULL; - proftime_T start; + proftime_T start; memset(stat, 0, sizeof(searchstat_T)); @@ -4636,12 +4636,12 @@ 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) { - pos_T pos = curwin->w_cursor; + pos_T pos = curwin->w_cursor; char_u *pattern = NULL; - int maxcount = SEARCH_STAT_DEF_MAX_COUNT; - long timeout = SEARCH_STAT_DEF_TIMEOUT; - bool recompute = true; - searchstat_T stat; + int maxcount = SEARCH_STAT_DEF_MAX_COUNT; + long timeout = SEARCH_STAT_DEF_TIMEOUT; + bool recompute = true; + searchstat_T stat; tv_dict_alloc_ret(rettv); diff --git a/src/nvim/sha256.c b/src/nvim/sha256.c index a2378cc202..9d6a2f2c41 100644 --- a/src/nvim/sha256.c +++ b/src/nvim/sha256.c @@ -51,8 +51,7 @@ void sha256_start(context_sha256_T *ctx) ctx->state[7] = 0x5BE0CD19; } -static void sha256_process(context_sha256_T *ctx, - const char_u data[SHA256_BUFFER_SIZE]) +static void sha256_process(context_sha256_T *ctx, const char_u data[SHA256_BUFFER_SIZE]) { uint32_t temp1, temp2, W[SHA256_BUFFER_SIZE]; uint32_t A, B, C, D, E, F, G, H; @@ -88,7 +87,7 @@ static void sha256_process(context_sha256_T *ctx, #define R(t) \ (W[t] = S1(W[t - 2]) + W[t - 7] + \ - S0(W[t - 15]) + W[t - 16]) + S0(W[t - 15]) + W[t - 16]) #define P(a, b, c, d, e, f, g, h, x, K) { \ temp1 = h + S3(e) + F1(e, f, g) + K + x; \ @@ -188,7 +187,7 @@ void sha256_update(context_sha256_T *ctx, const char_u *input, size_t length) uint32_t left = ctx->total[0] & (SHA256_BUFFER_SIZE-1); // left < buf size - ctx->total[0] += (uint32_t) length; + ctx->total[0] += (uint32_t)length; ctx->total[0] &= 0xFFFFFFFF; if (ctx->total[0] < length) { @@ -262,8 +261,8 @@ void sha256_finish(context_sha256_T *ctx, char_u digest[SHA256_SUM_SIZE]) /// /// @returns hex digest of "buf[buf_len]" in a static array. /// if "salt" is not NULL also do "salt[salt_len]". -const char *sha256_bytes(const uint8_t *restrict buf, size_t buf_len, - const uint8_t *restrict salt, size_t salt_len) +const char *sha256_bytes(const uint8_t *restrict buf, size_t buf_len, const uint8_t *restrict salt, + size_t salt_len) { char_u sha256sum[SHA256_SUM_SIZE]; static char hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 7d277fe5c8..25c9823dc7 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -1,51 +1,50 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include <stdlib.h> -#include <stddef.h> -#include <stdbool.h> -#include <string.h> -#include <inttypes.h> -#include <errno.h> #include <assert.h> - +#include <errno.h> +#include <inttypes.h> #include <msgpack.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> #include <uv.h> -#include "nvim/os/os.h" -#include "nvim/os/time.h" -#include "nvim/vim.h" -#include "nvim/pos.h" -#include "nvim/ascii.h" -#include "nvim/shada.h" -#include "nvim/message.h" -#include "nvim/globals.h" -#include "nvim/memory.h" -#include "nvim/mark.h" -#include "nvim/macros.h" -#include "nvim/ops.h" -#include "nvim/garray.h" -#include "nvim/option.h" -#include "nvim/msgpack_rpc/helpers.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/ascii.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" +#include "nvim/eval/decode.h" +#include "nvim/eval/encode.h" +#include "nvim/eval/typval.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" -#include "nvim/search.h" -#include "nvim/regexp.h" -#include "nvim/eval/typval.h" -#include "nvim/version.h" -#include "nvim/path.h" #include "nvim/fileio.h" -#include "nvim/os/fileio.h" -#include "nvim/strings.h" -#include "nvim/quickfix.h" -#include "nvim/eval/encode.h" -#include "nvim/eval/decode.h" +#include "nvim/garray.h" +#include "nvim/globals.h" #include "nvim/lib/khash.h" #include "nvim/lib/kvec.h" +#include "nvim/macros.h" +#include "nvim/mark.h" +#include "nvim/memory.h" +#include "nvim/message.h" +#include "nvim/msgpack_rpc/helpers.h" +#include "nvim/ops.h" +#include "nvim/option.h" +#include "nvim/os/fileio.h" +#include "nvim/os/os.h" +#include "nvim/os/time.h" +#include "nvim/path.h" +#include "nvim/pos.h" +#include "nvim/quickfix.h" +#include "nvim/regexp.h" +#include "nvim/search.h" +#include "nvim/shada.h" +#include "nvim/strings.h" +#include "nvim/version.h" +#include "nvim/vim.h" #ifdef HAVE_BE64TOH # define _BSD_SOURCE 1 @@ -67,24 +66,24 @@ KHASH_MAP_INIT_STR(fnamebufs, buf_T *) KHASH_SET_INIT_STR(strset) #define copy_option_part(src, dest, ...) \ - ((char *) copy_option_part((char_u **) src, (char_u *) dest, __VA_ARGS__)) + ((char *)copy_option_part((char_u **)src, (char_u *)dest, __VA_ARGS__)) #define find_shada_parameter(...) \ - ((const char *) find_shada_parameter(__VA_ARGS__)) + ((const char *)find_shada_parameter(__VA_ARGS__)) #define home_replace_save(a, b) \ - ((char *)home_replace_save(a, (char_u *)b)) + ((char *)home_replace_save(a, (char_u *)b)) #define home_replace(a, b, c, d, e) \ - home_replace(a, (char_u *)b, (char_u *)c, d, e) + home_replace(a, (char_u *)b, (char_u *)c, d, e) #define vim_rename(a, b) \ - (vim_rename((char_u *)a, (char_u *)b)) + (vim_rename((char_u *)a, (char_u *)b)) #define mb_strnicmp(a, b, c) \ - (mb_strnicmp((char_u *)a, (char_u *)b, c)) + (mb_strnicmp((char_u *)a, (char_u *)b, c)) #define path_try_shorten_fname(b) \ - ((char *)path_try_shorten_fname((char_u *)b)) + ((char *)path_try_shorten_fname((char_u *)b)) #define buflist_new(ffname, sfname, ...) \ - (buflist_new((char_u *)ffname, (char_u *)sfname, __VA_ARGS__)) -#define os_isdir(f) (os_isdir((char_u *) f)) -#define regtilde(s, m) ((char *) regtilde((char_u *) s, m)) -#define path_tail_with_sep(f) ((char *) path_tail_with_sep((char_u *)f)) + (buflist_new((char_u *)ffname, (char_u *)sfname, __VA_ARGS__)) +#define os_isdir(f) (os_isdir((char_u *)f)) +#define regtilde(s, m) ((char *)regtilde((char_u *)s, m)) +#define path_tail_with_sep(f) ((char *)path_tail_with_sep((char_u *)f)) #define SEARCH_KEY_MAGIC "sm" #define SEARCH_KEY_SMARTCASE "sc" @@ -172,7 +171,7 @@ typedef enum { kSDItemBufferList = 9, ///< Buffer list. kSDItemLocalMark = 10, ///< Buffer-local mark. kSDItemChange = 11, ///< Item from buffer change list. -#define SHADA_LAST_ENTRY ((uint64_t) kSDItemChange) +#define SHADA_LAST_ENTRY ((uint64_t)kSDItemChange) } ShadaEntryType; /// Possible results when reading ShaDa file @@ -202,11 +201,11 @@ enum SRNIFlags { kSDReadHeader = (1 << kSDItemHeader), ///< Determines whether header should ///< be read (it is usually ignored). kSDReadUndisableableData = ( - (1 << kSDItemSearchPattern) - | (1 << kSDItemSubString) - | (1 << kSDItemJump)), ///< Data reading which cannot be disabled by - ///< &shada or other options except for disabling - ///< reading ShaDa as a whole. + (1 << kSDItemSearchPattern) + | (1 << kSDItemSubString) + | (1 << kSDItemJump)), ///< Data reading which cannot be disabled by + ///< &shada or other options except for disabling + ///< reading ShaDa as a whole. kSDReadRegisters = (1 << kSDItemRegister), ///< Determines whether registers ///< should be read (may only be ///< disabled when writing, but @@ -434,13 +433,13 @@ typedef struct sd_write_def { #endif #define DEF_SDE(name, attr, ...) \ - [kSDItem##name] = { \ - .timestamp = 0, \ - .type = kSDItem##name, \ - .data = { \ - .attr = { __VA_ARGS__ } \ - } \ - } + [kSDItem##name] = { \ + .timestamp = 0, \ + .type = kSDItem##name, \ + .data = { \ + .attr = { __VA_ARGS__ } \ + } \ + } #define DEFAULT_POS { 1, 0, 0 } static const pos_T default_pos = DEFAULT_POS; static const ShadaEntry sd_default_values[] = { @@ -475,9 +474,9 @@ static const ShadaEntry sd_default_values[] = { DEF_SDE(Variable, global_var, .name = NULL, .value = { - .v_type = VAR_UNKNOWN, - .vval = { .v_string = NULL } - }, + .v_type = VAR_UNKNOWN, + .vval = { .v_string = NULL } + }, .additional_elements = NULL), DEF_SDE(GlobalMark, filemark, .name = '"', @@ -533,17 +532,16 @@ static inline void hmll_init(HMLList *const hmll, const size_t size) /// /// @return `for` cycle header (use `HMLL_FORALL(hmll, cur_entry) {body}`). #define HMLL_FORALL(hmll, cur_entry, code) \ - for (HMLListEntry *cur_entry = (hmll)->first; cur_entry != NULL; \ - cur_entry = cur_entry->next) { \ - code \ - } \ + for (HMLListEntry *cur_entry = (hmll)->first; cur_entry != NULL; \ + cur_entry = cur_entry->next) { \ + code \ + } \ /// Remove entry from the linked list /// /// @param hmll List to remove from. /// @param hmll_entry Entry to remove. -static inline void hmll_remove(HMLList *const hmll, - HMLListEntry *const hmll_entry) +static inline void hmll_remove(HMLList *const hmll, HMLListEntry *const hmll_entry) FUNC_ATTR_NONNULL_ALL { if (hmll_entry == hmll->last_free_entry - 1) { @@ -580,9 +578,7 @@ static inline void hmll_remove(HMLList *const hmll, /// to insert at the first entry. /// @param[in] data Data to insert. /// @param[in] can_free_entry True if data can be freed. -static inline void hmll_insert(HMLList *const hmll, - HMLListEntry *hmll_entry, - const ShadaEntry data, +static inline void hmll_insert(HMLList *const hmll, HMLListEntry *hmll_entry, const ShadaEntry data, const bool can_free_entry) FUNC_ATTR_NONNULL_ARG(1) { @@ -595,11 +591,11 @@ static inline void hmll_insert(HMLList *const hmll, } HMLListEntry *target_entry; if (hmll->free_entry == NULL) { - assert((size_t) (hmll->last_free_entry - hmll->entries) + assert((size_t)(hmll->last_free_entry - hmll->entries) == hmll->num_entries); target_entry = hmll->last_free_entry++; } else { - assert((size_t) (hmll->last_free_entry - hmll->entries) - 1 + assert((size_t)(hmll->last_free_entry - hmll->entries) - 1 == hmll->num_entries); target_entry = hmll->free_entry; hmll->free_entry = NULL; @@ -637,10 +633,10 @@ static inline void hmll_insert(HMLList *const hmll, /// /// @return `for` cycle header (use `HMLL_FORALL(hmll, cur_entry) {body}`). #define HMLL_ITER_BACK(hmll, cur_entry, code) \ - for (cur_entry = (hmll)->last; cur_entry != NULL; \ - cur_entry = cur_entry->prev) { \ - code \ - } + for (cur_entry = (hmll)->last; cur_entry != NULL; \ + cur_entry = cur_entry->prev) { \ + code \ + } /// Free linked list /// @@ -655,8 +651,7 @@ static inline void hmll_dealloc(HMLList *const hmll) /// Wrapper for reading from file descriptors /// /// @return -1 or number of bytes read. -static ptrdiff_t read_file(ShaDaReadDef *const sd_reader, void *const dest, - const size_t size) +static ptrdiff_t read_file(ShaDaReadDef *const sd_reader, void *const dest, const size_t size) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { const ptrdiff_t ret = file_read(sd_reader->cookie, dest, size); @@ -678,14 +673,13 @@ static int read_char(ShaDaReadDef *const sd_reader) if (read_bytes != 1) { return EOF; } - return (int) ret; + return (int)ret; } /// Wrapper for writing to file descriptors /// /// @return -1 or number of bytes written. -static ptrdiff_t write_file(ShaDaWriteDef *const sd_writer, - const void *const dest, +static ptrdiff_t write_file(ShaDaWriteDef *const sd_writer, const void *const dest, const size_t size) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { @@ -720,8 +714,7 @@ static void close_sd_writer(ShaDaWriteDef *const sd_writer) /// /// @return FAIL in case of failure, OK in case of success. May set /// sd_reader->eof or sd_reader->error. -static int sd_reader_skip_read(ShaDaReadDef *const sd_reader, - const size_t offset) +static int sd_reader_skip_read(ShaDaReadDef *const sd_reader, const size_t offset) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { const ptrdiff_t skip_bytes = file_skip(sd_reader->cookie, offset); @@ -749,8 +742,7 @@ static int sd_reader_skip_read(ShaDaReadDef *const sd_reader, /// /// @return kSDReadStatusReadError, kSDReadStatusNotShaDa or /// kSDReadStatusSuccess. -static ShaDaReadResult sd_reader_skip(ShaDaReadDef *const sd_reader, - const size_t offset) +static ShaDaReadResult sd_reader_skip(ShaDaReadDef *const sd_reader, const size_t offset) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { if (sd_reader->skip(sd_reader, offset) != OK) { @@ -762,7 +754,7 @@ static ShaDaReadResult sd_reader_skip(ShaDaReadDef *const sd_reader, emsgf(_(RCERR "Error while reading ShaDa file: " "last entry specified that it occupies %" PRIu64 " bytes, " "but file ended earlier"), - (uint64_t) offset); + (uint64_t)offset); return kSDReadStatusNotShaDa; } abort(); @@ -776,8 +768,7 @@ static ShaDaReadResult sd_reader_skip(ShaDaReadDef *const sd_reader, /// @param[out] sd_reader Location where reader structure will be saved. /// /// @return libuv error in case of error, 0 otherwise. -static int open_shada_file_for_reading(const char *const fname, - ShaDaReadDef *sd_reader) +static int open_shada_file_for_reading(const char *const fname, ShaDaReadDef *sd_reader) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { int error; @@ -819,7 +810,7 @@ static void close_file(void *cookie) static inline bool in_bufset(const khash_t(bufset) *const set, const buf_T *buf) FUNC_ATTR_PURE { - return kh_get(bufset, set, (uintptr_t) buf) != kh_end(set); + return kh_get(bufset, set, (uintptr_t)buf) != kh_end(set); } /// Check whether string is in the given set @@ -837,7 +828,7 @@ static inline bool in_strset(const khash_t(strset) *const set, char *str) /// Msgpack callback for writing to ShaDaWriteDef* static int msgpack_sd_writer_write(void *data, const char *buf, size_t len) { - ShaDaWriteDef *const sd_writer = (ShaDaWriteDef *) data; + ShaDaWriteDef *const sd_writer = (ShaDaWriteDef *)data; ptrdiff_t written_bytes = sd_writer->write(sd_writer, buf, len); if (written_bytes == -1) { emsgf(_(SERR "System error while writing ShaDa file: %s"), @@ -910,10 +901,8 @@ static int shada_read_file(const char *const file, const int flags) /// @param[out] hist Location where iteration results should be saved. /// /// @return Next iteration state. -static const void *shada_hist_iter(const void *const iter, - const uint8_t history_type, - const bool zero, - ShadaEntry *const hist) +static const void *shada_hist_iter(const void *const iter, const uint8_t history_type, + const bool zero, ShadaEntry *const hist) FUNC_ATTR_NONNULL_ARG(4) FUNC_ATTR_WARN_UNUSED_RESULT { histentry_T hist_he; @@ -927,9 +916,9 @@ static const void *shada_hist_iter(const void *const iter, .data = { .history_item = { .histtype = history_type, - .string = (char *) hist_he.hisstr, - .sep = (char) (history_type == HIST_SEARCH - ? (char) hist_he.hisstr[STRLEN(hist_he.hisstr) + 1] + .string = (char *)hist_he.hisstr, + .sep = (char)(history_type == HIST_SEARCH + ? (char)hist_he.hisstr[STRLEN(hist_he.hisstr) + 1] : 0), .additional_elements = hist_he.additional_elements, } @@ -954,8 +943,8 @@ static const void *shada_hist_iter(const void *const iter, /// be used. Must be true only if inserting /// entry from current Neovim history. /// @param[in] can_free_entry True if entry can be freed. -static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry, - const bool do_iter, const bool can_free_entry) +static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry, const bool do_iter, + const bool can_free_entry) FUNC_ATTR_NONNULL_ALL { if (do_iter) { @@ -1008,11 +997,8 @@ static void hms_insert(HistoryMergerState *const hms_p, const ShadaEntry entry, /// @param[in] do_merge Prepare structure for merging elements. /// @param[in] reading If true, then merger is reading history for use /// in Neovim. -static inline void hms_init(HistoryMergerState *const hms_p, - const uint8_t history_type, - const size_t num_elements, - const bool do_merge, - const bool reading) +static inline void hms_init(HistoryMergerState *const hms_p, const uint8_t history_type, + const size_t num_elements, const bool do_merge, const bool reading) FUNC_ATTR_NONNULL_ALL { hmll_init(&hms_p->hmll, num_elements); @@ -1027,8 +1013,7 @@ static inline void hms_init(HistoryMergerState *const hms_p, /// /// @param[in,out] hms_p Merger structure into which history should be /// inserted. -static inline void hms_insert_whole_neovim_history( - HistoryMergerState *const hms_p) +static inline void hms_insert_whole_neovim_history(HistoryMergerState *const hms_p) FUNC_ATTR_NONNULL_ALL { while (hms_p->last_hist_entry.type != kSDItemMissing) { @@ -1048,21 +1033,20 @@ static inline void hms_insert_whole_neovim_history( /// @param[out] new_hisidx New last history entry index. /// @param[out] new_hisnum Amount of history items in merger structure. static inline void hms_to_he_array(const HistoryMergerState *const hms_p, - histentry_T *const hist_array, - int *const new_hisidx, + histentry_T *const hist_array, int *const new_hisidx, int *const new_hisnum) FUNC_ATTR_NONNULL_ALL { histentry_T *hist = hist_array; 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->hisnum = (int)(hist - hist_array) + 1; + hist->hisstr = (char_u *)cur_entry->data.data.history_item.string; hist->additional_elements = - cur_entry->data.data.history_item.additional_elements; + cur_entry->data.data.history_item.additional_elements; hist++; }) - *new_hisnum = (int) (hist - hist_array); + *new_hisnum = (int)(hist - hist_array); *new_hisidx = *new_hisnum - 1; } @@ -1083,7 +1067,7 @@ static inline void hms_dealloc(HistoryMergerState *const hms_p) /// /// @return for cycle header. Use `HMS_ITER(hms_p, cur_entry) {body}`. #define HMS_ITER(hms_p, cur_entry, code) \ - HMLL_FORALL(&((hms_p)->hmll), cur_entry, code) + HMLL_FORALL(&((hms_p)->hmll), cur_entry, code) /// Find buffer for given buffer name (cached) /// @@ -1091,8 +1075,7 @@ static inline void hms_dealloc(HistoryMergerState *const hms_p) /// @param[in] fname File name to find. /// /// @return Pointer to the buffer or NULL. -static buf_T *find_buffer(khash_t(fnamebufs) *const fname_bufs, - const char *const fname) +static buf_T *find_buffer(khash_t(fnamebufs) *const fname_bufs, const char *const fname) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { int kh_ret; @@ -1123,7 +1106,7 @@ static inline bool marks_equal(const pos_T a, const pos_T b) entry, fname_cond, free_func, fin_func, \ idxadj_func, afterfree_func) \ do { \ - const int jl_len = (int) jumps_size; \ + const int jl_len = (int)jumps_size; \ int i; \ for (i = jl_len; i > 0; i--) { \ const jumps_type jl_entry = jumps[i - 1]; \ @@ -1140,17 +1123,17 @@ static inline bool marks_equal(const pos_T a, const pos_T b) free_func(jumps[0]); \ i--; \ if (i > 0) { \ - memmove(&jumps[0], &jumps[1], sizeof(jumps[1]) * (size_t) i); \ + memmove(&jumps[0], &jumps[1], sizeof(jumps[1]) * (size_t)i); \ } \ } else if (i != jl_len) { \ memmove(&jumps[i + 1], &jumps[i], \ - sizeof(jumps[0]) * (size_t) (jl_len - i)); \ + sizeof(jumps[0]) * (size_t)(jl_len - i)); \ } \ } else if (i == 0) { \ if (jl_len == JUMPLISTSIZE) { \ i = -1; \ } else if (jl_len > 0) { \ - memmove(&jumps[1], &jumps[0], sizeof(jumps[0]) * (size_t) jl_len); \ + memmove(&jumps[1], &jumps[0], sizeof(jumps[0]) * (size_t)jl_len); \ } \ } \ if (i != -1) { \ @@ -1177,8 +1160,8 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) const bool get_old_files = (flags & (kShaDaGetOldfiles | kShaDaForceit) && (force || tv_list_len(oldfiles_list) == 0)); const bool want_marks = flags & kShaDaWantMarks; - const unsigned srni_flags = (unsigned) ( - (flags & kShaDaWantInfo + const unsigned srni_flags = (unsigned)( + (flags & kShaDaWantInfo ? (kSDReadUndisableableData | kSDReadRegisters | kSDReadGlobalMarks @@ -1190,11 +1173,11 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) && ARGCOUNT == 0 ? kSDReadBufferList : 0)) - : 0) - | (want_marks && get_shada_parameter('\'') > 0 + : 0) + | (want_marks && get_shada_parameter('\'') > 0 ? kSDReadLocalMarks | kSDReadChanges : 0) - | (get_old_files + | (get_old_files ? kSDReadLocalMarks : 0)); if (srni_flags == 0) { @@ -1204,7 +1187,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) HistoryMergerState hms[HIST_COUNT]; if (srni_flags & kSDReadHistory) { for (uint8_t i = 0; i < HIST_COUNT; i++) { - hms_init(&hms[i], i, (size_t) p_hi, true, true); + hms_init(&hms[i], i, (size_t)p_hi, true, true); } } ShadaEntry cur_entry; @@ -1219,253 +1202,237 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) while ((srni_ret = shada_read_next_item(sd_reader, &cur_entry, srni_flags, 0)) != kSDReadStatusFinished) { switch (srni_ret) { - case kSDReadStatusSuccess: { - break; - } - case kSDReadStatusFinished: { - // Should be handled by the while condition. - abort(); - } - case kSDReadStatusNotShaDa: - case kSDReadStatusReadError: { - goto shada_read_main_cycle_end; - } - case kSDReadStatusMalformed: { - continue; - } + case kSDReadStatusSuccess: + break; + case kSDReadStatusFinished: + // Should be handled by the while condition. + abort(); + case kSDReadStatusNotShaDa: + case kSDReadStatusReadError: + goto shada_read_main_cycle_end; + case kSDReadStatusMalformed: + continue; } switch (cur_entry.type) { - case kSDItemMissing: { - abort(); - } - case kSDItemUnknown: { - break; - } - case kSDItemHeader: { - shada_free_shada_entry(&cur_entry); - break; - } - case kSDItemSearchPattern: { - if (!force) { - SearchPattern pat; - (cur_entry.data.search_pattern.is_substitute_pattern + case kSDItemMissing: + abort(); + case kSDItemUnknown: + break; + case kSDItemHeader: + shada_free_shada_entry(&cur_entry); + break; + case kSDItemSearchPattern: + if (!force) { + SearchPattern pat; + (cur_entry.data.search_pattern.is_substitute_pattern ? &get_substitute_pattern : &get_search_pattern)(&pat); - if (pat.pat != NULL && pat.timestamp >= cur_entry.timestamp) { - shada_free_shada_entry(&cur_entry); - break; - } + if (pat.pat != NULL && pat.timestamp >= cur_entry.timestamp) { + shada_free_shada_entry(&cur_entry); + break; } - (cur_entry.data.search_pattern.is_substitute_pattern + } + (cur_entry.data.search_pattern.is_substitute_pattern ? &set_substitute_pattern : &set_search_pattern)((SearchPattern) { - .magic = cur_entry.data.search_pattern.magic, - .no_scs = !cur_entry.data.search_pattern.smartcase, - .off = { - .dir = cur_entry.data.search_pattern.search_backward ? '?' : '/', - .line = cur_entry.data.search_pattern.has_line_offset, - .end = cur_entry.data.search_pattern.place_cursor_at_end, - .off = cur_entry.data.search_pattern.offset, - }, - .pat = (char_u *) cur_entry.data.search_pattern.pat, - .additional_data = cur_entry.data.search_pattern.additional_data, - .timestamp = cur_entry.timestamp, - }); - if (cur_entry.data.search_pattern.is_last_used) { - set_last_used_pattern( - cur_entry.data.search_pattern.is_substitute_pattern); - set_no_hlsearch(!cur_entry.data.search_pattern.highlighted); - } - // Do not free shada entry: its allocated memory was saved above. - break; - } - case kSDItemSubString: { - if (!force) { - SubReplacementString sub; - sub_get_replacement(&sub); - if (sub.sub != NULL && sub.timestamp >= cur_entry.timestamp) { - shada_free_shada_entry(&cur_entry); - break; - } - } - sub_set_replacement((SubReplacementString) { - .sub = cur_entry.data.sub_string.sub, - .timestamp = cur_entry.timestamp, - .additional_elements = cur_entry.data.sub_string.additional_elements, - }); - // Without using regtilde and without / &cpo flag previous substitute - // 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) regtilde(cur_entry.data.sub_string.sub, p_magic); - // Do not free shada entry: its allocated memory was saved above. - break; + .magic = cur_entry.data.search_pattern.magic, + .no_scs = !cur_entry.data.search_pattern.smartcase, + .off = { + .dir = cur_entry.data.search_pattern.search_backward ? '?' : '/', + .line = cur_entry.data.search_pattern.has_line_offset, + .end = cur_entry.data.search_pattern.place_cursor_at_end, + .off = cur_entry.data.search_pattern.offset, + }, + .pat = (char_u *)cur_entry.data.search_pattern.pat, + .additional_data = cur_entry.data.search_pattern.additional_data, + .timestamp = cur_entry.timestamp, + }); + if (cur_entry.data.search_pattern.is_last_used) { + set_last_used_pattern(cur_entry.data.search_pattern.is_substitute_pattern); + set_no_hlsearch(!cur_entry.data.search_pattern.highlighted); } - case kSDItemHistoryEntry: { - if (cur_entry.data.history_item.histtype >= HIST_COUNT) { + // Do not free shada entry: its allocated memory was saved above. + break; + case kSDItemSubString: + if (!force) { + SubReplacementString sub; + sub_get_replacement(&sub); + if (sub.sub != NULL && sub.timestamp >= cur_entry.timestamp) { shada_free_shada_entry(&cur_entry); break; } - hms_insert(hms + cur_entry.data.history_item.histtype, cur_entry, true, - true); - // Do not free shada entry: its allocated memory was saved above. + } + sub_set_replacement((SubReplacementString) { + .sub = cur_entry.data.sub_string.sub, + .timestamp = cur_entry.timestamp, + .additional_elements = cur_entry.data.sub_string.additional_elements, + }); + // Without using regtilde and without / &cpo flag previous substitute + // 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)regtilde(cur_entry.data.sub_string.sub, p_magic); + // Do not free shada entry: its allocated memory was saved above. + break; + case kSDItemHistoryEntry: + if (cur_entry.data.history_item.histtype >= HIST_COUNT) { + shada_free_shada_entry(&cur_entry); + break; + } + hms_insert(hms + cur_entry.data.history_item.histtype, cur_entry, true, + true); + // Do not free shada entry: its allocated memory was saved above. + break; + case kSDItemRegister: + if (cur_entry.data.reg.type != kMTCharWise + && cur_entry.data.reg.type != kMTLineWise + && cur_entry.data.reg.type != kMTBlockWise) { + shada_free_shada_entry(&cur_entry); break; } - case kSDItemRegister: { - if (cur_entry.data.reg.type != kMTCharWise - && cur_entry.data.reg.type != kMTLineWise - && cur_entry.data.reg.type != kMTBlockWise) { + if (!force) { + const yankreg_T *const reg = op_reg_get(cur_entry.data.reg.name); + if (reg == NULL || reg->timestamp >= cur_entry.timestamp) { shada_free_shada_entry(&cur_entry); break; } - if (!force) { - const yankreg_T *const reg = op_reg_get(cur_entry.data.reg.name); - if (reg == NULL || reg->timestamp >= cur_entry.timestamp) { - shada_free_shada_entry(&cur_entry); - break; - } - } - if (!op_reg_set(cur_entry.data.reg.name, (yankreg_T) { - .y_array = (char_u **)cur_entry.data.reg.contents, - .y_size = cur_entry.data.reg.contents_size, - .y_type = cur_entry.data.reg.type, - .y_width = (colnr_T) cur_entry.data.reg.width, - .timestamp = cur_entry.timestamp, - .additional_data = cur_entry.data.reg.additional_data, - }, cur_entry.data.reg.is_unnamed)) { - shada_free_shada_entry(&cur_entry); - } - // Do not free shada entry: its allocated memory was saved above. - break; } - case kSDItemVariable: { - var_set_global(cur_entry.data.global_var.name, - cur_entry.data.global_var.value); - cur_entry.data.global_var.value.v_type = VAR_UNKNOWN; + if (!op_reg_set(cur_entry.data.reg.name, (yankreg_T) { + .y_array = (char_u **)cur_entry.data.reg.contents, + .y_size = cur_entry.data.reg.contents_size, + .y_type = cur_entry.data.reg.type, + .y_width = (colnr_T)cur_entry.data.reg.width, + .timestamp = cur_entry.timestamp, + .additional_data = cur_entry.data.reg.additional_data, + }, cur_entry.data.reg.is_unnamed)) { shada_free_shada_entry(&cur_entry); - break; } - case kSDItemJump: - case kSDItemGlobalMark: { - buf_T *buf = find_buffer(&fname_bufs, cur_entry.data.filemark.fname); - if (buf != NULL) { - XFREE_CLEAR(cur_entry.data.filemark.fname); - } - xfmark_T fm = (xfmark_T) { - .fname = (char_u *) (buf == NULL + // Do not free shada entry: its allocated memory was saved above. + break; + case kSDItemVariable: + var_set_global(cur_entry.data.global_var.name, + cur_entry.data.global_var.value); + cur_entry.data.global_var.value.v_type = VAR_UNKNOWN; + shada_free_shada_entry(&cur_entry); + break; + case kSDItemJump: + case kSDItemGlobalMark: { + buf_T *buf = find_buffer(&fname_bufs, cur_entry.data.filemark.fname); + if (buf != NULL) { + XFREE_CLEAR(cur_entry.data.filemark.fname); + } + xfmark_T fm = (xfmark_T) { + .fname = (char_u *)(buf == NULL ? cur_entry.data.filemark.fname : NULL), - .fmark = { - .mark = cur_entry.data.filemark.mark, - .fnum = (buf == NULL ? 0 : buf->b_fnum), - .timestamp = cur_entry.timestamp, - .additional_data = cur_entry.data.filemark.additional_data, - }, - }; - if (cur_entry.type == kSDItemGlobalMark) { - if (!mark_set_global(cur_entry.data.filemark.name, fm, !force)) { - shada_free_shada_entry(&cur_entry); - break; - } - } else { + .fmark = { + .mark = cur_entry.data.filemark.mark, + .fnum = (buf == NULL ? 0 : buf->b_fnum), + .timestamp = cur_entry.timestamp, + .additional_data = cur_entry.data.filemark.additional_data, + }, + }; + if (cur_entry.type == kSDItemGlobalMark) { + if (!mark_set_global(cur_entry.data.filemark.name, fm, !force)) { + shada_free_shada_entry(&cur_entry); + break; + } + } else { #define SDE_TO_XFMARK(entry) fm #define ADJUST_IDX(i) \ - if (curwin->w_jumplistidx >= i \ - && curwin->w_jumplistidx + 1 <= curwin->w_jumplistlen) { \ - curwin->w_jumplistidx++; \ - } + if (curwin->w_jumplistidx >= i \ + && curwin->w_jumplistidx + 1 <= curwin->w_jumplistlen) { \ + curwin->w_jumplistidx++; \ + } #define DUMMY_AFTERFREE(entry) - MERGE_JUMPS(curwin->w_jumplistlen, curwin->w_jumplist, xfmark_T, - fmark.timestamp, fmark.mark, cur_entry, - (buf == NULL + 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), - free_xfmark, SDE_TO_XFMARK, ADJUST_IDX, DUMMY_AFTERFREE); + free_xfmark, SDE_TO_XFMARK, ADJUST_IDX, DUMMY_AFTERFREE); #undef SDE_TO_XFMARK #undef ADJUST_IDX #undef DUMMY_AFTERFREE - } - // Do not free shada entry: its allocated memory was saved above. - break; } - case kSDItemBufferList: { - for (size_t i = 0; i < cur_entry.data.buffer_list.size; i++) { - char *const sfname = path_try_shorten_fname( - cur_entry.data.buffer_list.buffers[i].fname); - buf_T *const buf = buflist_new( - cur_entry.data.buffer_list.buffers[i].fname, sfname, 0, - BLN_LISTED); - if (buf != NULL) { - RESET_FMARK(&buf->b_last_cursor, - cur_entry.data.buffer_list.buffers[i].pos, 0); - buflist_setfpos(buf, curwin, buf->b_last_cursor.mark.lnum, - buf->b_last_cursor.mark.col, false); - buf->additional_data = - cur_entry.data.buffer_list.buffers[i].additional_data; - cur_entry.data.buffer_list.buffers[i].additional_data = NULL; - } + // Do not free shada entry: its allocated memory was saved above. + break; + } + case kSDItemBufferList: + for (size_t i = 0; i < cur_entry.data.buffer_list.size; i++) { + char *const sfname = path_try_shorten_fname(cur_entry.data.buffer_list.buffers[i].fname); + buf_T *const buf = buflist_new(cur_entry.data.buffer_list.buffers[i].fname, sfname, 0, + BLN_LISTED); + if (buf != NULL) { + RESET_FMARK(&buf->b_last_cursor, + cur_entry.data.buffer_list.buffers[i].pos, 0); + buflist_setfpos(buf, curwin, buf->b_last_cursor.mark.lnum, + buf->b_last_cursor.mark.col, false); + buf->additional_data = + cur_entry.data.buffer_list.buffers[i].additional_data; + cur_entry.data.buffer_list.buffers[i].additional_data = NULL; } - shada_free_shada_entry(&cur_entry); - break; } - case kSDItemChange: - case kSDItemLocalMark: { - if (get_old_files && !in_strset(&oldfiles_set, - cur_entry.data.filemark.fname)) { - char *fname = cur_entry.data.filemark.fname; - if (want_marks) { - // Do not bother with allocating memory for the string if already - // allocated string from cur_entry can be used. It cannot be used if - // want_marks is set because this way it may be used for a mark. - fname = xstrdup(fname); - } - int kh_ret; - (void)kh_put(strset, &oldfiles_set, fname, &kh_ret); - tv_list_append_allocated_string(oldfiles_list, fname); - if (!want_marks) { - // Avoid free because this string was already used. - cur_entry.data.filemark.fname = NULL; - } + shada_free_shada_entry(&cur_entry); + break; + case kSDItemChange: + case kSDItemLocalMark: { + if (get_old_files && !in_strset(&oldfiles_set, + cur_entry.data.filemark.fname)) { + char *fname = cur_entry.data.filemark.fname; + if (want_marks) { + // Do not bother with allocating memory for the string if already + // allocated string from cur_entry can be used. It cannot be used if + // want_marks is set because this way it may be used for a mark. + fname = xstrdup(fname); } + int kh_ret; + (void)kh_put(strset, &oldfiles_set, fname, &kh_ret); + tv_list_append_allocated_string(oldfiles_list, fname); if (!want_marks) { - shada_free_shada_entry(&cur_entry); - break; + // Avoid free because this string was already used. + cur_entry.data.filemark.fname = NULL; } - buf_T *buf = find_buffer(&fname_bufs, cur_entry.data.filemark.fname); - if (buf == NULL) { + } + if (!want_marks) { + shada_free_shada_entry(&cur_entry); + break; + } + buf_T *buf = find_buffer(&fname_bufs, cur_entry.data.filemark.fname); + if (buf == NULL) { + shada_free_shada_entry(&cur_entry); + break; + } + const fmark_T fm = (fmark_T) { + .mark = cur_entry.data.filemark.mark, + .fnum = 0, + .timestamp = cur_entry.timestamp, + .additional_data = cur_entry.data.filemark.additional_data, + }; + if (cur_entry.type == kSDItemLocalMark) { + if (!mark_set_local(cur_entry.data.filemark.name, buf, fm, !force)) { shada_free_shada_entry(&cur_entry); break; } - const fmark_T fm = (fmark_T) { - .mark = cur_entry.data.filemark.mark, - .fnum = 0, - .timestamp = cur_entry.timestamp, - .additional_data = cur_entry.data.filemark.additional_data, - }; - if (cur_entry.type == kSDItemLocalMark) { - if (!mark_set_local(cur_entry.data.filemark.name, buf, fm, !force)) { - shada_free_shada_entry(&cur_entry); - break; - } - } else { - int kh_ret; - (void) kh_put(bufset, &cl_bufs, (uintptr_t) buf, &kh_ret); + } else { + int kh_ret; + (void)kh_put(bufset, &cl_bufs, (uintptr_t)buf, &kh_ret); #define SDE_TO_FMARK(entry) fm #define AFTERFREE(entry) (entry).data.filemark.fname = NULL #define DUMMY_IDX_ADJ(i) - MERGE_JUMPS(buf->b_changelistlen, buf->b_changelist, fmark_T, - timestamp, mark, cur_entry, true, - free_fmark, SDE_TO_FMARK, DUMMY_IDX_ADJ, AFTERFREE); + MERGE_JUMPS(buf->b_changelistlen, buf->b_changelist, fmark_T, + timestamp, mark, cur_entry, true, + free_fmark, SDE_TO_FMARK, DUMMY_IDX_ADJ, AFTERFREE); #undef SDE_TO_FMARK #undef AFTERFREE #undef DUMMY_IDX_ADJ - } - // Do not free shada entry: except for fname, its allocated memory (i.e. - // additional_data attribute contents if non-NULL) was saved above. - xfree(cur_entry.data.filemark.fname); - break; } + // Do not free shada entry: except for fname, its allocated memory (i.e. + // additional_data attribute contents if non-NULL) was saved above. + xfree(cur_entry.data.filemark.fname); + break; + } } } shada_read_main_cycle_end: @@ -1490,7 +1457,7 @@ shada_read_main_cycle_end: } if (cl_bufs.n_occupied) { FOR_ALL_TAB_WINDOWS(tp, wp) { - (void) tp; + (void)tp; if (in_bufset(&cl_bufs, wp->w_buffer)) { wp->w_changelistidx = wp->w_buffer->b_changelistlen; } @@ -1499,7 +1466,7 @@ shada_read_main_cycle_end: kh_dealloc(bufset, &cl_bufs); const char *key; kh_foreach_key(&fname_bufs, key, { - xfree((void *) key); + xfree((void *)key); }) kh_dealloc(fnamebufs, &fname_bufs); kh_dealloc(strset, &oldfiles_set); @@ -1544,33 +1511,33 @@ static char *shada_filename(const char *file) // 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); - file = (const char *) &(NameBuff[0]); + file = (const char *)&(NameBuff[0]); } } return xstrdup(file); } #define PACK_STATIC_STR(s) \ - do { \ - msgpack_pack_str(spacker, sizeof(s) - 1); \ - msgpack_pack_str_body(spacker, s, sizeof(s) - 1); \ - } while (0) + do { \ + msgpack_pack_str(spacker, sizeof(s) - 1); \ + msgpack_pack_str_body(spacker, s, sizeof(s) - 1); \ + } while (0) #define PACK_STRING(s) \ - do { \ - const String s_ = (s); \ - msgpack_pack_str(spacker, s_.size); \ - if (s_.size) { \ - msgpack_pack_str_body(spacker, s_.data, s_.size); \ - } \ - } while (0) + do { \ + const String s_ = (s); \ + msgpack_pack_str(spacker, s_.size); \ + if (s_.size) { \ + msgpack_pack_str_body(spacker, s_.data, s_.size); \ + } \ + } while (0) #define PACK_BIN(s) \ - do { \ - const String s_ = (s); \ - msgpack_pack_bin(spacker, s_.size); \ - if (s_.size > 0) { \ - msgpack_pack_bin_body(spacker, s_.data, s_.size); \ - } \ - } while (0) + do { \ + const String s_ = (s); \ + msgpack_pack_bin(spacker, s_.size); \ + if (s_.size > 0) { \ + msgpack_pack_bin_body(spacker, s_.data, s_.size); \ + } \ + } while (0) /// Write single ShaDa entry /// @@ -1580,8 +1547,7 @@ static char *shada_filename(const char *file) /// restrictions. /// /// @return kSDWriteSuccessfull, kSDWriteFailed or kSDWriteIgnError. -static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, - ShadaEntry entry, +static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, ShadaEntry entry, const size_t max_kbyte) FUNC_ATTR_NONNULL_ALL { @@ -1625,244 +1591,239 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, #define CHECK_DEFAULT(entry, attr) \ (sd_default_values[entry.type].data.attr == entry.data.attr) #define ONE_IF_NOT_DEFAULT(entry, attr) \ - ((size_t) (!CHECK_DEFAULT(entry, attr))) + ((size_t)(!CHECK_DEFAULT(entry, attr))) switch (entry.type) { - case kSDItemMissing: { - abort(); + case kSDItemMissing: + abort(); + case kSDItemUnknown: + if (spacker->callback(spacker->data, entry.data.unknown_item.contents, + (unsigned)entry.data.unknown_item.size) == -1) { + goto shada_pack_entry_error; } - case kSDItemUnknown: { - if (spacker->callback(spacker->data, entry.data.unknown_item.contents, - (unsigned) entry.data.unknown_item.size) == -1) { - goto shada_pack_entry_error; - } - break; + break; + case kSDItemHistoryEntry: { + const bool is_hist_search = + entry.data.history_item.histtype == HIST_SEARCH; + const size_t arr_size = 2 + (size_t)is_hist_search + (size_t)( + tv_list_len(entry.data. + history_item. + additional_elements)); + msgpack_pack_array(spacker, arr_size); + msgpack_pack_uint8(spacker, entry.data.history_item.histtype); + PACK_BIN(cstr_as_string(entry.data.history_item.string)); + if (is_hist_search) { + msgpack_pack_uint8(spacker, (uint8_t)entry.data.history_item.sep); } - case kSDItemHistoryEntry: { - const bool is_hist_search = - entry.data.history_item.histtype == HIST_SEARCH; - const size_t arr_size = 2 + (size_t)is_hist_search + (size_t)( - tv_list_len(entry.data.history_item.additional_elements)); - msgpack_pack_array(spacker, arr_size); - msgpack_pack_uint8(spacker, entry.data.history_item.histtype); - PACK_BIN(cstr_as_string(entry.data.history_item.string)); - if (is_hist_search) { - msgpack_pack_uint8(spacker, (uint8_t)entry.data.history_item.sep); - } - DUMP_ADDITIONAL_ELEMENTS(entry.data.history_item.additional_elements, - "history entry item"); - break; - } - case kSDItemVariable: { - if (entry.data.global_var.value.v_type == VAR_TYPE_BLOB) { - // Strings and Blobs both pack as msgpack BINs; differentiate them by - // storing an additional VAR_TYPE_BLOB element alongside Blobs - list_T *const list = tv_list_alloc(1); - tv_list_append_number(list, VAR_TYPE_BLOB); - entry.data.global_var.additional_elements = list; - } - const size_t arr_size = 2 + (size_t)( - tv_list_len(entry.data.global_var.additional_elements)); - msgpack_pack_array(spacker, arr_size); - const String varname = cstr_as_string(entry.data.global_var.name); - PACK_BIN(varname); - char vardesc[256] = "variable g:"; - memcpy(&vardesc[sizeof("variable g:") - 1], varname.data, - varname.size + 1); - if (encode_vim_to_msgpack(spacker, &entry.data.global_var.value, vardesc) - == FAIL) { - ret = kSDWriteIgnError; - EMSG2(_(WERR "Failed to write variable %s"), - entry.data.global_var.name); - goto shada_pack_entry_error; - } - DUMP_ADDITIONAL_ELEMENTS(entry.data.global_var.additional_elements, - "variable item"); - break; + DUMP_ADDITIONAL_ELEMENTS(entry.data.history_item.additional_elements, + "history entry item"); + break; + } + case kSDItemVariable: { + if (entry.data.global_var.value.v_type == VAR_TYPE_BLOB) { + // Strings and Blobs both pack as msgpack BINs; differentiate them by + // storing an additional VAR_TYPE_BLOB element alongside Blobs + list_T *const list = tv_list_alloc(1); + tv_list_append_number(list, VAR_TYPE_BLOB); + entry.data.global_var.additional_elements = list; } - case kSDItemSubString: { - const size_t arr_size = 1 + (size_t)( - tv_list_len(entry.data.sub_string.additional_elements)); - msgpack_pack_array(spacker, arr_size); - PACK_BIN(cstr_as_string(entry.data.sub_string.sub)); - DUMP_ADDITIONAL_ELEMENTS(entry.data.sub_string.additional_elements, - "sub string item"); - break; + const size_t arr_size = 2 + (size_t)( + tv_list_len(entry.data.global_var.additional_elements)); + msgpack_pack_array(spacker, arr_size); + const String varname = cstr_as_string(entry.data.global_var.name); + PACK_BIN(varname); + char vardesc[256] = "variable g:"; + memcpy(&vardesc[sizeof("variable g:") - 1], varname.data, + varname.size + 1); + if (encode_vim_to_msgpack(spacker, &entry.data.global_var.value, vardesc) + == FAIL) { + ret = kSDWriteIgnError; + EMSG2(_(WERR "Failed to write variable %s"), + entry.data.global_var.name); + goto shada_pack_entry_error; } - case kSDItemSearchPattern: { - const size_t map_size = (size_t) ( - 1 // Search pattern is always present - + ONE_IF_NOT_DEFAULT(entry, search_pattern.magic) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.is_last_used) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.smartcase) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.has_line_offset) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.place_cursor_at_end) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.is_substitute_pattern) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.highlighted) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.offset) - + ONE_IF_NOT_DEFAULT(entry, search_pattern.search_backward) - // finally, additional data: - + (size_t) ( - entry.data.search_pattern.additional_data + DUMP_ADDITIONAL_ELEMENTS(entry.data.global_var.additional_elements, + "variable item"); + break; + } + case kSDItemSubString: { + const size_t arr_size = 1 + (size_t)( + tv_list_len(entry.data.sub_string.additional_elements)); + msgpack_pack_array(spacker, arr_size); + PACK_BIN(cstr_as_string(entry.data.sub_string.sub)); + DUMP_ADDITIONAL_ELEMENTS(entry.data.sub_string.additional_elements, + "sub string item"); + break; + } + case kSDItemSearchPattern: { + const size_t map_size = (size_t)( + 1 // Search pattern is always present + + ONE_IF_NOT_DEFAULT(entry, search_pattern.magic) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.is_last_used) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.smartcase) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.has_line_offset) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.place_cursor_at_end) + + ONE_IF_NOT_DEFAULT(entry, + search_pattern.is_substitute_pattern) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.highlighted) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.offset) + + ONE_IF_NOT_DEFAULT(entry, search_pattern.search_backward) + // finally, additional data: + + (size_t)( + entry.data.search_pattern.additional_data ? entry.data.search_pattern.additional_data->dv_hashtab.ht_used : 0)); - msgpack_pack_map(spacker, map_size); - PACK_STATIC_STR(SEARCH_KEY_PAT); - PACK_BIN(cstr_as_string(entry.data.search_pattern.pat)); + msgpack_pack_map(spacker, map_size); + PACK_STATIC_STR(SEARCH_KEY_PAT); + PACK_BIN(cstr_as_string(entry.data.search_pattern.pat)); #define PACK_BOOL(entry, name, attr) \ - do { \ - if (!CHECK_DEFAULT(entry, search_pattern.attr)) { \ - PACK_STATIC_STR(name); \ - if (sd_default_values[entry.type].data.search_pattern.attr) { \ - msgpack_pack_false(spacker); \ - } else { \ - msgpack_pack_true(spacker); \ - } \ - } \ - } while (0) - PACK_BOOL(entry, SEARCH_KEY_MAGIC, magic); - PACK_BOOL(entry, SEARCH_KEY_IS_LAST_USED, is_last_used); - PACK_BOOL(entry, SEARCH_KEY_SMARTCASE, smartcase); - PACK_BOOL(entry, SEARCH_KEY_HAS_LINE_OFFSET, has_line_offset); - PACK_BOOL(entry, SEARCH_KEY_PLACE_CURSOR_AT_END, place_cursor_at_end); - PACK_BOOL(entry, SEARCH_KEY_IS_SUBSTITUTE_PATTERN, is_substitute_pattern); - PACK_BOOL(entry, SEARCH_KEY_HIGHLIGHTED, highlighted); - PACK_BOOL(entry, SEARCH_KEY_BACKWARD, search_backward); - if (!CHECK_DEFAULT(entry, search_pattern.offset)) { - PACK_STATIC_STR(SEARCH_KEY_OFFSET); - msgpack_pack_int64(spacker, entry.data.search_pattern.offset); - } -#undef PACK_BOOL - DUMP_ADDITIONAL_DATA(entry.data.search_pattern.additional_data, - "search pattern item"); - break; + do { \ + if (!CHECK_DEFAULT(entry, search_pattern.attr)) { \ + PACK_STATIC_STR(name); \ + if (sd_default_values[entry.type].data.search_pattern.attr) { \ + msgpack_pack_false(spacker); \ + } else { \ + msgpack_pack_true(spacker); \ + } \ + } \ + } while (0) + PACK_BOOL(entry, SEARCH_KEY_MAGIC, magic); + PACK_BOOL(entry, SEARCH_KEY_IS_LAST_USED, is_last_used); + PACK_BOOL(entry, SEARCH_KEY_SMARTCASE, smartcase); + PACK_BOOL(entry, SEARCH_KEY_HAS_LINE_OFFSET, has_line_offset); + PACK_BOOL(entry, SEARCH_KEY_PLACE_CURSOR_AT_END, place_cursor_at_end); + PACK_BOOL(entry, SEARCH_KEY_IS_SUBSTITUTE_PATTERN, is_substitute_pattern); + PACK_BOOL(entry, SEARCH_KEY_HIGHLIGHTED, highlighted); + PACK_BOOL(entry, SEARCH_KEY_BACKWARD, search_backward); + if (!CHECK_DEFAULT(entry, search_pattern.offset)) { + PACK_STATIC_STR(SEARCH_KEY_OFFSET); + msgpack_pack_int64(spacker, entry.data.search_pattern.offset); } - case kSDItemChange: - case kSDItemGlobalMark: - case kSDItemLocalMark: - case kSDItemJump: { - const size_t map_size = (size_t) ( - 1 // File name - + ONE_IF_NOT_DEFAULT(entry, filemark.mark.lnum) - + ONE_IF_NOT_DEFAULT(entry, filemark.mark.col) - + ONE_IF_NOT_DEFAULT(entry, filemark.name) - // Additional entries, if any: - + (size_t) ( - entry.data.filemark.additional_data == NULL +#undef PACK_BOOL + DUMP_ADDITIONAL_DATA(entry.data.search_pattern.additional_data, + "search pattern item"); + break; + } + case kSDItemChange: + case kSDItemGlobalMark: + case kSDItemLocalMark: + case kSDItemJump: { + const size_t map_size = (size_t)( + 1 // File name + + ONE_IF_NOT_DEFAULT(entry, filemark.mark.lnum) + + ONE_IF_NOT_DEFAULT(entry, filemark.mark.col) + + ONE_IF_NOT_DEFAULT(entry, filemark.name) + // Additional entries, if any: + + (size_t)( + entry.data.filemark.additional_data == NULL ? 0 : entry.data.filemark.additional_data->dv_hashtab.ht_used)); - msgpack_pack_map(spacker, map_size); - PACK_STATIC_STR(KEY_FILE); - PACK_BIN(cstr_as_string(entry.data.filemark.fname)); - if (!CHECK_DEFAULT(entry, filemark.mark.lnum)) { - PACK_STATIC_STR(KEY_LNUM); - msgpack_pack_long(spacker, entry.data.filemark.mark.lnum); - } - if (!CHECK_DEFAULT(entry, filemark.mark.col)) { - PACK_STATIC_STR(KEY_COL); - msgpack_pack_long(spacker, entry.data.filemark.mark.col); - } - assert(entry.type == kSDItemJump || entry.type == kSDItemChange + msgpack_pack_map(spacker, map_size); + PACK_STATIC_STR(KEY_FILE); + PACK_BIN(cstr_as_string(entry.data.filemark.fname)); + if (!CHECK_DEFAULT(entry, filemark.mark.lnum)) { + PACK_STATIC_STR(KEY_LNUM); + msgpack_pack_long(spacker, entry.data.filemark.mark.lnum); + } + if (!CHECK_DEFAULT(entry, filemark.mark.col)) { + PACK_STATIC_STR(KEY_COL); + msgpack_pack_long(spacker, entry.data.filemark.mark.col); + } + assert(entry.type == kSDItemJump || entry.type == kSDItemChange ? CHECK_DEFAULT(entry, filemark.name) : true); - if (!CHECK_DEFAULT(entry, filemark.name)) { - PACK_STATIC_STR(KEY_NAME_CHAR); - msgpack_pack_uint8(spacker, (uint8_t) entry.data.filemark.name); - } - DUMP_ADDITIONAL_DATA(entry.data.filemark.additional_data, - "mark (change, jump, global or local) item"); - break; + if (!CHECK_DEFAULT(entry, filemark.name)) { + PACK_STATIC_STR(KEY_NAME_CHAR); + msgpack_pack_uint8(spacker, (uint8_t)entry.data.filemark.name); } - case kSDItemRegister: { - const size_t map_size = (size_t) ( - 2 // Register contents and name - + ONE_IF_NOT_DEFAULT(entry, reg.type) - + ONE_IF_NOT_DEFAULT(entry, reg.width) - + ONE_IF_NOT_DEFAULT(entry, reg.is_unnamed) - // Additional entries, if any: - + (size_t) (entry.data.reg.additional_data == NULL + DUMP_ADDITIONAL_DATA(entry.data.filemark.additional_data, + "mark (change, jump, global or local) item"); + break; + } + case kSDItemRegister: { + const size_t map_size = (size_t)( + 2 // Register contents and name + + ONE_IF_NOT_DEFAULT(entry, reg.type) + + ONE_IF_NOT_DEFAULT(entry, reg.width) + + ONE_IF_NOT_DEFAULT(entry, reg.is_unnamed) + // Additional entries, if any: + + (size_t)(entry.data.reg.additional_data == NULL ? 0 : entry.data.reg.additional_data->dv_hashtab.ht_used)); - msgpack_pack_map(spacker, map_size); - PACK_STATIC_STR(REG_KEY_CONTENTS); - msgpack_pack_array(spacker, entry.data.reg.contents_size); - for (size_t i = 0; i < entry.data.reg.contents_size; i++) { - PACK_BIN(cstr_as_string(entry.data.reg.contents[i])); - } - PACK_STATIC_STR(KEY_NAME_CHAR); - msgpack_pack_char(spacker, entry.data.reg.name); - if (!CHECK_DEFAULT(entry, reg.type)) { - PACK_STATIC_STR(REG_KEY_TYPE); - msgpack_pack_uint8(spacker, (uint8_t)entry.data.reg.type); - } - if (!CHECK_DEFAULT(entry, reg.width)) { - PACK_STATIC_STR(REG_KEY_WIDTH); - msgpack_pack_uint64(spacker, (uint64_t) entry.data.reg.width); - } - if (!CHECK_DEFAULT(entry, reg.is_unnamed)) { - PACK_STATIC_STR(REG_KEY_UNNAMED); - if (entry.data.reg.is_unnamed) { - msgpack_pack_true(spacker); - } else { - msgpack_pack_false(spacker); - } + msgpack_pack_map(spacker, map_size); + PACK_STATIC_STR(REG_KEY_CONTENTS); + msgpack_pack_array(spacker, entry.data.reg.contents_size); + for (size_t i = 0; i < entry.data.reg.contents_size; i++) { + PACK_BIN(cstr_as_string(entry.data.reg.contents[i])); + } + PACK_STATIC_STR(KEY_NAME_CHAR); + msgpack_pack_char(spacker, entry.data.reg.name); + if (!CHECK_DEFAULT(entry, reg.type)) { + PACK_STATIC_STR(REG_KEY_TYPE); + msgpack_pack_uint8(spacker, (uint8_t)entry.data.reg.type); + } + if (!CHECK_DEFAULT(entry, reg.width)) { + PACK_STATIC_STR(REG_KEY_WIDTH); + msgpack_pack_uint64(spacker, (uint64_t)entry.data.reg.width); + } + if (!CHECK_DEFAULT(entry, reg.is_unnamed)) { + PACK_STATIC_STR(REG_KEY_UNNAMED); + if (entry.data.reg.is_unnamed) { + msgpack_pack_true(spacker); + } else { + msgpack_pack_false(spacker); } - DUMP_ADDITIONAL_DATA(entry.data.reg.additional_data, "register item"); - break; } - case kSDItemBufferList: { - msgpack_pack_array(spacker, entry.data.buffer_list.size); - for (size_t i = 0; i < entry.data.buffer_list.size; i++) { - const size_t map_size = (size_t) ( - 1 // Buffer name - + (size_t) (entry.data.buffer_list.buffers[i].pos.lnum - != default_pos.lnum) - + (size_t) (entry.data.buffer_list.buffers[i].pos.col - != default_pos.col) - // Additional entries, if any: - + (size_t) ( - entry.data.buffer_list.buffers[i].additional_data == NULL + DUMP_ADDITIONAL_DATA(entry.data.reg.additional_data, "register item"); + break; + } + case kSDItemBufferList: + msgpack_pack_array(spacker, entry.data.buffer_list.size); + for (size_t i = 0; i < entry.data.buffer_list.size; i++) { + const size_t map_size = (size_t)( + 1 // Buffer name + + (size_t)(entry.data.buffer_list.buffers[i].pos.lnum + != default_pos.lnum) + + (size_t)(entry.data.buffer_list.buffers[i].pos.col + != default_pos.col) + // Additional entries, if any: + + (size_t)( + entry.data.buffer_list.buffers[i].additional_data + == NULL ? 0 : (entry.data.buffer_list.buffers[i].additional_data ->dv_hashtab.ht_used))); - msgpack_pack_map(spacker, map_size); - PACK_STATIC_STR(KEY_FILE); - PACK_BIN(cstr_as_string(entry.data.buffer_list.buffers[i].fname)); - if (entry.data.buffer_list.buffers[i].pos.lnum != 1) { - PACK_STATIC_STR(KEY_LNUM); - msgpack_pack_uint64( - spacker, (uint64_t) entry.data.buffer_list.buffers[i].pos.lnum); - } - if (entry.data.buffer_list.buffers[i].pos.col != 0) { - PACK_STATIC_STR(KEY_COL); - msgpack_pack_uint64( - spacker, (uint64_t) entry.data.buffer_list.buffers[i].pos.col); - } - DUMP_ADDITIONAL_DATA(entry.data.buffer_list.buffers[i].additional_data, - "buffer list subitem"); + msgpack_pack_map(spacker, map_size); + PACK_STATIC_STR(KEY_FILE); + PACK_BIN(cstr_as_string(entry.data.buffer_list.buffers[i].fname)); + if (entry.data.buffer_list.buffers[i].pos.lnum != 1) { + PACK_STATIC_STR(KEY_LNUM); + msgpack_pack_uint64(spacker, (uint64_t)entry.data.buffer_list.buffers[i].pos.lnum); } - break; + if (entry.data.buffer_list.buffers[i].pos.col != 0) { + PACK_STATIC_STR(KEY_COL); + msgpack_pack_uint64(spacker, (uint64_t)entry.data.buffer_list.buffers[i].pos.col); + } + DUMP_ADDITIONAL_DATA(entry.data.buffer_list.buffers[i].additional_data, + "buffer list subitem"); } - case kSDItemHeader: { - msgpack_pack_map(spacker, entry.data.header.size); - for (size_t i = 0; i < entry.data.header.size; i++) { - PACK_STRING(entry.data.header.items[i].key); - const Object obj = entry.data.header.items[i].value; - switch (obj.type) { - case kObjectTypeString: { - PACK_BIN(obj.data.string); - break; - } - case kObjectTypeInteger: { - msgpack_pack_int64(spacker, (int64_t) obj.data.integer); - break; - } - default: { - abort(); - } - } + break; + case kSDItemHeader: + msgpack_pack_map(spacker, entry.data.header.size); + for (size_t i = 0; i < entry.data.header.size; i++) { + PACK_STRING(entry.data.header.items[i].key); + const Object obj = entry.data.header.items[i].value; + switch (obj.type) { + case kObjectTypeString: + PACK_BIN(obj.data.string); + break; + case kObjectTypeInteger: + msgpack_pack_int64(spacker, (int64_t)obj.data.integer); + break; + default: + abort(); } - break; } + break; } #undef CHECK_DEFAULT #undef ONE_IF_NOT_DEFAULT @@ -1872,17 +1833,17 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer, goto shada_pack_entry_error; } } else { - if (msgpack_pack_uint64(packer, (uint64_t) entry.type) == -1) { + if (msgpack_pack_uint64(packer, (uint64_t)entry.type) == -1) { goto shada_pack_entry_error; } } - if (msgpack_pack_uint64(packer, (uint64_t) entry.timestamp) == -1) { + if (msgpack_pack_uint64(packer, (uint64_t)entry.timestamp) == -1) { goto shada_pack_entry_error; } if (sbuf.size > 0) { - if ((msgpack_pack_uint64(packer, (uint64_t) sbuf.size) == -1) + if ((msgpack_pack_uint64(packer, (uint64_t)sbuf.size) == -1) || (packer->callback(packer->data, sbuf.data, - (unsigned) sbuf.size) == -1)) { + (unsigned)sbuf.size) == -1)) { goto shada_pack_entry_error; } } @@ -1905,9 +1866,9 @@ shada_pack_entry_error: /// @param[in] entry Entry written. /// @param[in] max_kbyte Maximum size of an item in KiB. Zero means no /// restrictions. -static inline ShaDaWriteResult shada_pack_pfreed_entry( - msgpack_packer *const packer, PossiblyFreedShadaEntry entry, - const size_t max_kbyte) +static inline ShaDaWriteResult shada_pack_pfreed_entry(msgpack_packer *const packer, + PossiblyFreedShadaEntry entry, + const size_t max_kbyte) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE { ShaDaWriteResult ret = kSDWriteSuccessfull; @@ -1945,9 +1906,10 @@ static int compare_file_marks(const void *a, const void *b) /// /// @return kSDReadStatusNotShaDa, kSDReadStatusReadError or /// kSDReadStatusSuccess. -static inline ShaDaReadResult shada_parse_msgpack( - ShaDaReadDef *const sd_reader, const size_t length, - msgpack_unpacked *ret_unpacked, char **const ret_buf) +static inline ShaDaReadResult shada_parse_msgpack(ShaDaReadDef *const sd_reader, + const size_t length, + msgpack_unpacked *ret_unpacked, + char **const ret_buf) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1) { const uintmax_t initial_fpos = sd_reader->fpos; @@ -1964,47 +1926,42 @@ shada_parse_msgpack_read_next: {} msgpack_unpacked unpacked; msgpack_unpacked_init(&unpacked); const msgpack_unpack_return result = - msgpack_unpack_next(&unpacked, buf, length, &off); + msgpack_unpack_next(&unpacked, buf, length, &off); ShaDaReadResult ret = kSDReadStatusSuccess; switch (result) { - case MSGPACK_UNPACK_SUCCESS: { - if (off < length) { - goto shada_parse_msgpack_extra_bytes; - } - break; + case MSGPACK_UNPACK_SUCCESS: + if (off < length) { + goto shada_parse_msgpack_extra_bytes; } - case MSGPACK_UNPACK_PARSE_ERROR: { - emsgf(_(RCERR "Failed to parse ShaDa file due to a msgpack parser error " - "at position %" PRIu64), - (uint64_t) initial_fpos); - ret = kSDReadStatusNotShaDa; - break; + break; + case MSGPACK_UNPACK_PARSE_ERROR: + emsgf(_(RCERR "Failed to parse ShaDa file due to a msgpack parser error " + "at position %" PRIu64), + (uint64_t)initial_fpos); + ret = kSDReadStatusNotShaDa; + break; + case MSGPACK_UNPACK_NOMEM_ERROR: + if (!did_try_to_free) { + did_try_to_free = true; + try_to_free_memory(); + goto shada_parse_msgpack_read_next; } - case MSGPACK_UNPACK_NOMEM_ERROR: { - if (!did_try_to_free) { - did_try_to_free = true; - try_to_free_memory(); - goto shada_parse_msgpack_read_next; - } - EMSG(_(e_outofmem)); - ret = kSDReadStatusReadError; - break; - } - case MSGPACK_UNPACK_CONTINUE: { - emsgf(_(RCERR "Failed to parse ShaDa file: incomplete msgpack string " - "at position %" PRIu64), - (uint64_t) initial_fpos); - ret = kSDReadStatusNotShaDa; - break; - } - case MSGPACK_UNPACK_EXTRA_BYTES: { + EMSG(_(e_outofmem)); + ret = kSDReadStatusReadError; + break; + case MSGPACK_UNPACK_CONTINUE: + emsgf(_(RCERR "Failed to parse ShaDa file: incomplete msgpack string " + "at position %" PRIu64), + (uint64_t)initial_fpos); + ret = kSDReadStatusNotShaDa; + break; + case MSGPACK_UNPACK_EXTRA_BYTES: shada_parse_msgpack_extra_bytes: - emsgf(_(RCERR "Failed to parse ShaDa file: extra bytes in msgpack string " - "at position %" PRIu64), - (uint64_t) initial_fpos); - ret = kSDReadStatusNotShaDa; - break; - } + emsgf(_(RCERR "Failed to parse ShaDa file: extra bytes in msgpack string " + "at position %" PRIu64), + (uint64_t)initial_fpos); + ret = kSDReadStatusNotShaDa; + break; } if (ret_buf != NULL && ret == kSDReadStatusSuccess) { if (ret_unpacked == NULL) { @@ -2034,81 +1991,67 @@ static const char *shada_format_entry(const ShadaEntry entry) vim_snprintf(S_LEN(ret), "%s", "[ ] ts=%" PRIu64 " "); // ^ Space for `can_free_entry` switch (entry.type) { - case kSDItemMissing: { - vim_snprintf_add(S_LEN(ret), "Missing"); - break; - } - case kSDItemHeader: { - vim_snprintf_add(S_LEN(ret), "Header { TODO }"); - break; - } - case kSDItemBufferList: { - vim_snprintf_add(S_LEN(ret), "BufferList { TODO }"); - break; - } - case kSDItemUnknown: { - vim_snprintf_add(S_LEN(ret), "Unknown { TODO }"); - break; - } - case kSDItemSearchPattern: { - vim_snprintf_add(S_LEN(ret), "SearchPattern { TODO }"); - break; - } - case kSDItemSubString: { - vim_snprintf_add(S_LEN(ret), "SubString { TODO }"); - break; - } - case kSDItemHistoryEntry: { - vim_snprintf_add(S_LEN(ret), "HistoryEntry { TODO }"); - break; - } - case kSDItemRegister: { - vim_snprintf_add(S_LEN(ret), "Register { TODO }"); - break; - } - case kSDItemVariable: { - vim_snprintf_add(S_LEN(ret), "Variable { TODO }"); - break; - } + case kSDItemMissing: + vim_snprintf_add(S_LEN(ret), "Missing"); + break; + case kSDItemHeader: + vim_snprintf_add(S_LEN(ret), "Header { TODO }"); + break; + case kSDItemBufferList: + vim_snprintf_add(S_LEN(ret), "BufferList { TODO }"); + break; + case kSDItemUnknown: + vim_snprintf_add(S_LEN(ret), "Unknown { TODO }"); + break; + case kSDItemSearchPattern: + vim_snprintf_add(S_LEN(ret), "SearchPattern { TODO }"); + break; + case kSDItemSubString: + vim_snprintf_add(S_LEN(ret), "SubString { TODO }"); + break; + case kSDItemHistoryEntry: + vim_snprintf_add(S_LEN(ret), "HistoryEntry { TODO }"); + break; + case kSDItemRegister: + vim_snprintf_add(S_LEN(ret), "Register { TODO }"); + break; + case kSDItemVariable: + vim_snprintf_add(S_LEN(ret), "Variable { TODO }"); + break; #define FORMAT_MARK_ENTRY(entry_name, name_fmt, name_fmt_arg) \ - do { \ - typval_T ad_tv = { \ - .v_type = VAR_DICT, \ - .vval.v_dict = entry.data.filemark.additional_data \ - }; \ - size_t ad_len; \ - char *const ad = encode_tv2string(&ad_tv, &ad_len); \ - vim_snprintf_add( \ - S_LEN(ret), \ - entry_name " {" name_fmt " file=[%zu]\"%.512s\", " \ - "pos={l=%" PRIdLINENR ",c=%" PRIdCOLNR ",a=%" PRIdCOLNR "}, " \ - "ad={%p:[%zu]%.64s} }", \ - name_fmt_arg, \ - strlen(entry.data.filemark.fname), \ - entry.data.filemark.fname, \ - entry.data.filemark.mark.lnum, \ - entry.data.filemark.mark.col, \ - entry.data.filemark.mark.coladd, \ - (void *)entry.data.filemark.additional_data, \ - ad_len, \ - ad); \ - } while (0) - case kSDItemGlobalMark: { - FORMAT_MARK_ENTRY("GlobalMark", " name='%c',", entry.data.filemark.name); - break; - } - case kSDItemChange: { - FORMAT_MARK_ENTRY("Change", "%s", ""); - break; - } - case kSDItemLocalMark: { - FORMAT_MARK_ENTRY("LocalMark", " name='%c',", entry.data.filemark.name); - break; - } - case kSDItemJump: { - FORMAT_MARK_ENTRY("Jump", "%s", ""); - break; - } + do { \ + typval_T ad_tv = { \ + .v_type = VAR_DICT, \ + .vval.v_dict = entry.data.filemark.additional_data \ + }; \ + size_t ad_len; \ + char *const ad = encode_tv2string(&ad_tv, &ad_len); \ + vim_snprintf_add(S_LEN(ret), \ + entry_name " {" name_fmt " file=[%zu]\"%.512s\", " \ + "pos={l=%" PRIdLINENR ",c=%" PRIdCOLNR ",a=%" PRIdCOLNR "}, " \ + "ad={%p:[%zu]%.64s} }", \ + name_fmt_arg, \ + strlen(entry.data.filemark.fname), \ + entry.data.filemark.fname, \ + entry.data.filemark.mark.lnum, \ + entry.data.filemark.mark.col, \ + entry.data.filemark.mark.coladd, \ + (void *)entry.data.filemark.additional_data, \ + ad_len, \ + ad); \ + } while (0) + case kSDItemGlobalMark: + FORMAT_MARK_ENTRY("GlobalMark", " name='%c',", entry.data.filemark.name); + break; + case kSDItemChange: + FORMAT_MARK_ENTRY("Change", "%s", ""); + break; + case kSDItemLocalMark: + FORMAT_MARK_ENTRY("LocalMark", " name='%c',", entry.data.filemark.name); + break; + case kSDItemJump: + FORMAT_MARK_ENTRY("Jump", "%s", ""); + break; #undef FORMAT_MARK_ENTRY } return ret; @@ -2119,8 +2062,7 @@ static const char *shada_format_entry(const ShadaEntry entry) /// @param[in] entry ShaDa entry to format. /// /// @return string representing ShaDa entry in a static buffer. -static const char *shada_format_pfreed_entry( - const PossiblyFreedShadaEntry pfs_entry) +static const char *shada_format_pfreed_entry(const PossiblyFreedShadaEntry pfs_entry) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_UNUSED FUNC_ATTR_NONNULL_RET { char *ret = (char *)shada_format_entry(pfs_entry.data); @@ -2136,10 +2078,11 @@ static const char *shada_format_pfreed_entry( /// @param[in,out] ret_wms Location where results are saved. /// @param[out] packer MessagePack packer for entries which are not /// merged. -static inline ShaDaWriteResult shada_read_when_writing( - ShaDaReadDef *const sd_reader, const unsigned srni_flags, - const size_t max_kbyte, WriteMergerState *const wms, - msgpack_packer *const packer) +static inline ShaDaWriteResult shada_read_when_writing(ShaDaReadDef *const sd_reader, + const unsigned srni_flags, + const size_t max_kbyte, + WriteMergerState *const wms, + msgpack_packer *const packer) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { ShaDaWriteResult ret = kSDWriteSuccessfull; @@ -2149,217 +2092,202 @@ static inline ShaDaWriteResult shada_read_when_writing( max_kbyte)) != kSDReadStatusFinished) { switch (srni_ret) { - case kSDReadStatusSuccess: { - break; - } - case kSDReadStatusFinished: { - // Should be handled by the while condition. - abort(); - } - case kSDReadStatusNotShaDa: { - ret = kSDWriteReadNotShada; - FALLTHROUGH; - } - case kSDReadStatusReadError: { - return ret; - } - case kSDReadStatusMalformed: { - continue; - } + case kSDReadStatusSuccess: + break; + case kSDReadStatusFinished: + // Should be handled by the while condition. + abort(); + case kSDReadStatusNotShaDa: + ret = kSDWriteReadNotShada; + FALLTHROUGH; + case kSDReadStatusReadError: + return ret; + case kSDReadStatusMalformed: + continue; } #define COMPARE_WITH_ENTRY(wms_entry_, entry) \ - do { \ - PossiblyFreedShadaEntry *const wms_entry = (wms_entry_); \ - if (wms_entry->data.type != kSDItemMissing) { \ - if (wms_entry->data.timestamp >= (entry).timestamp) { \ - shada_free_shada_entry(&(entry)); \ - break; \ - } \ - if (wms_entry->can_free_entry) { \ - shada_free_shada_entry(&wms_entry->data); \ - } \ + do { \ + PossiblyFreedShadaEntry *const wms_entry = (wms_entry_); \ + if (wms_entry->data.type != kSDItemMissing) { \ + if (wms_entry->data.timestamp >= (entry).timestamp) { \ + shada_free_shada_entry(&(entry)); \ + break; \ + } \ + if (wms_entry->can_free_entry) { \ + shada_free_shada_entry(&wms_entry->data); \ } \ - *wms_entry = pfs_entry; \ - } while (0) + } \ + *wms_entry = pfs_entry; \ + } while (0) const PossiblyFreedShadaEntry pfs_entry = { .can_free_entry = true, .data = entry, }; switch (entry.type) { - case kSDItemMissing: { + case kSDItemMissing: + break; + case kSDItemHeader: + case kSDItemBufferList: + abort(); + case kSDItemUnknown: + ret = shada_pack_entry(packer, entry, 0); + shada_free_shada_entry(&entry); + break; + case kSDItemSearchPattern: + COMPARE_WITH_ENTRY((entry.data.search_pattern.is_substitute_pattern + ? &wms->sub_search_pattern + : &wms->search_pattern), entry); + break; + case kSDItemSubString: + COMPARE_WITH_ENTRY(&wms->replacement, entry); + break; + case kSDItemHistoryEntry: + if (entry.data.history_item.histtype >= HIST_COUNT) { + ret = shada_pack_entry(packer, entry, 0); + shada_free_shada_entry(&entry); break; } - case kSDItemHeader: - case kSDItemBufferList: { - abort(); + if (wms->hms[entry.data.history_item.histtype].hmll.size != 0) { + hms_insert(&wms->hms[entry.data.history_item.histtype], entry, true, + true); + } else { + shada_free_shada_entry(&entry); } - case kSDItemUnknown: { + break; + case kSDItemRegister: { + const int idx = op_reg_index(entry.data.reg.name); + if (idx < 0) { ret = shada_pack_entry(packer, entry, 0); shada_free_shada_entry(&entry); break; } - case kSDItemSearchPattern: { - COMPARE_WITH_ENTRY((entry.data.search_pattern.is_substitute_pattern - ? &wms->sub_search_pattern - : &wms->search_pattern), entry); - break; - } - case kSDItemSubString: { - COMPARE_WITH_ENTRY(&wms->replacement, entry); - break; + COMPARE_WITH_ENTRY(&wms->registers[idx], entry); + break; + } + case kSDItemVariable: + if (!in_strset(&wms->dumped_variables, entry.data.global_var.name)) { + ret = shada_pack_entry(packer, entry, 0); } - case kSDItemHistoryEntry: { - if (entry.data.history_item.histtype >= HIST_COUNT) { - ret = shada_pack_entry(packer, entry, 0); - shada_free_shada_entry(&entry); - break; + shada_free_shada_entry(&entry); + break; + case kSDItemGlobalMark: + if (ascii_isdigit(entry.data.filemark.name)) { + bool processed_mark = false; + // Completely ignore numbered mark names, make a list sorted by + // timestamp. + for (size_t i = ARRAY_SIZE(wms->numbered_marks); i > 0; i--) { + ShadaEntry wms_entry = wms->numbered_marks[i - 1].data; + if (wms_entry.type != kSDItemGlobalMark) { + continue; + } + // Ignore duplicates. + if (wms_entry.timestamp == entry.timestamp + && (wms_entry.data.filemark.additional_data == NULL + && entry.data.filemark.additional_data == NULL) + && marks_equal(wms_entry.data.filemark.mark, + entry.data.filemark.mark) + && strcmp(wms_entry.data.filemark.fname, + entry.data.filemark.fname) == 0) { + shada_free_shada_entry(&entry); + processed_mark = true; + break; + } + if (wms_entry.timestamp >= entry.timestamp) { + processed_mark = true; + if (i < ARRAY_SIZE(wms->numbered_marks)) { + replace_numbered_mark(wms, i, pfs_entry); + } else { + shada_free_shada_entry(&entry); + } + break; + } } - if (wms->hms[entry.data.history_item.histtype].hmll.size != 0) { - hms_insert(&wms->hms[entry.data.history_item.histtype], entry, true, - true); - } else { - shada_free_shada_entry(&entry); + if (!processed_mark) { + replace_numbered_mark(wms, 0, pfs_entry); } - break; - } - case kSDItemRegister: { - const int idx = op_reg_index(entry.data.reg.name); + } else { + const int idx = mark_global_index(entry.data.filemark.name); if (idx < 0) { ret = shada_pack_entry(packer, entry, 0); shada_free_shada_entry(&entry); break; } - COMPARE_WITH_ENTRY(&wms->registers[idx], entry); - break; + COMPARE_WITH_ENTRY(&wms->global_marks[idx], entry); } - case kSDItemVariable: { - if (!in_strset(&wms->dumped_variables, entry.data.global_var.name)) { - ret = shada_pack_entry(packer, entry, 0); - } + break; + case kSDItemChange: + case kSDItemLocalMark: { + if (shada_removable(entry.data.filemark.fname)) { shada_free_shada_entry(&entry); break; } - case kSDItemGlobalMark: { - if (ascii_isdigit(entry.data.filemark.name)) { - bool processed_mark = false; - // Completely ignore numbered mark names, make a list sorted by - // timestamp. - for (size_t i = ARRAY_SIZE(wms->numbered_marks); i > 0; i--) { - ShadaEntry wms_entry = wms->numbered_marks[i - 1].data; - if (wms_entry.type != kSDItemGlobalMark) { - continue; - } - // Ignore duplicates. - if (wms_entry.timestamp == entry.timestamp - && (wms_entry.data.filemark.additional_data == NULL - && entry.data.filemark.additional_data == NULL) - && marks_equal(wms_entry.data.filemark.mark, - entry.data.filemark.mark) - && strcmp(wms_entry.data.filemark.fname, - entry.data.filemark.fname) == 0) { + const char *const fname = (const char *)entry.data.filemark.fname; + khiter_t k; + int kh_ret; + k = kh_put(file_marks, &wms->file_marks, fname, &kh_ret); + FileMarks *const filemarks = &kh_val(&wms->file_marks, k); + if (kh_ret > 0) { + memset(filemarks, 0, sizeof(*filemarks)); + } + if (entry.timestamp > filemarks->greatest_timestamp) { + filemarks->greatest_timestamp = entry.timestamp; + } + if (entry.type == kSDItemLocalMark) { + const int idx = mark_local_index(entry.data.filemark.name); + if (idx < 0) { + filemarks->additional_marks = xrealloc(filemarks->additional_marks, + (++filemarks->additional_marks_size + * sizeof(filemarks->additional_marks[0]))); + filemarks->additional_marks[filemarks->additional_marks_size - 1] = + entry; + } else { + PossiblyFreedShadaEntry *const wms_entry = &filemarks->marks[idx]; + if (wms_entry->data.type != kSDItemMissing) { + if (wms_entry->data.timestamp >= entry.timestamp) { shada_free_shada_entry(&entry); - processed_mark = true; break; } - if (wms_entry.timestamp >= entry.timestamp) { - processed_mark = true; - if (i < ARRAY_SIZE(wms->numbered_marks)) { - replace_numbered_mark(wms, i, pfs_entry); - } else { - shada_free_shada_entry(&entry); + if (wms_entry->can_free_entry) { + if (kh_key(&wms->file_marks, k) + == wms_entry->data.data.filemark.fname) { + kh_key(&wms->file_marks, k) = entry.data.filemark.fname; } - break; + shada_free_shada_entry(&wms_entry->data); } } - if (!processed_mark) { - replace_numbered_mark(wms, 0, pfs_entry); - } - } else { - const int idx = mark_global_index(entry.data.filemark.name); - if (idx < 0) { - ret = shada_pack_entry(packer, entry, 0); - shada_free_shada_entry(&entry); - break; - } - COMPARE_WITH_ENTRY(&wms->global_marks[idx], entry); - } - break; - } - case kSDItemChange: - case kSDItemLocalMark: { - if (shada_removable(entry.data.filemark.fname)) { - shada_free_shada_entry(&entry); - break; - } - const char *const fname = (const char *) entry.data.filemark.fname; - khiter_t k; - int kh_ret; - k = kh_put(file_marks, &wms->file_marks, fname, &kh_ret); - FileMarks *const filemarks = &kh_val(&wms->file_marks, k); - if (kh_ret > 0) { - memset(filemarks, 0, sizeof(*filemarks)); - } - if (entry.timestamp > filemarks->greatest_timestamp) { - filemarks->greatest_timestamp = entry.timestamp; + *wms_entry = pfs_entry; } - if (entry.type == kSDItemLocalMark) { - const int idx = mark_local_index(entry.data.filemark.name); - if (idx < 0) { - filemarks->additional_marks = xrealloc( - filemarks->additional_marks, - (++filemarks->additional_marks_size - * sizeof(filemarks->additional_marks[0]))); - filemarks->additional_marks[filemarks->additional_marks_size - 1] = - entry; - } else { - PossiblyFreedShadaEntry *const wms_entry = &filemarks->marks[idx]; - if (wms_entry->data.type != kSDItemMissing) { - if (wms_entry->data.timestamp >= entry.timestamp) { - shada_free_shada_entry(&entry); - break; - } - if (wms_entry->can_free_entry) { - if (kh_key(&wms->file_marks, k) - == wms_entry->data.data.filemark.fname) { - kh_key(&wms->file_marks, k) = entry.data.filemark.fname; - } - shada_free_shada_entry(&wms_entry->data); - } - } - *wms_entry = pfs_entry; - } - } else { + } else { #define FREE_POSSIBLY_FREED_SHADA_ENTRY(entry) \ - do { \ - if (entry.can_free_entry) { \ - shada_free_shada_entry(&entry.data); \ - } \ - } while (0) + do { \ + if (entry.can_free_entry) { \ + shada_free_shada_entry(&entry.data); \ + } \ + } while (0) #define SDE_TO_PFSDE(entry) \ - ((PossiblyFreedShadaEntry) { .can_free_entry = true, .data = entry }) + ((PossiblyFreedShadaEntry) { .can_free_entry = true, .data = entry }) #define AFTERFREE_DUMMY(entry) #define DUMMY_IDX_ADJ(i) - MERGE_JUMPS(filemarks->changes_size, filemarks->changes, - PossiblyFreedShadaEntry, data.timestamp, - data.data.filemark.mark, entry, true, - FREE_POSSIBLY_FREED_SHADA_ENTRY, SDE_TO_PFSDE, - DUMMY_IDX_ADJ, AFTERFREE_DUMMY); - } - break; - } - case kSDItemJump: { - MERGE_JUMPS(wms->jumps_size, wms->jumps, PossiblyFreedShadaEntry, - data.timestamp, data.data.filemark.mark, entry, - strcmp(jl_entry.data.data.filemark.fname, - entry.data.filemark.fname) == 0, + MERGE_JUMPS(filemarks->changes_size, filemarks->changes, + PossiblyFreedShadaEntry, data.timestamp, + data.data.filemark.mark, entry, true, FREE_POSSIBLY_FREED_SHADA_ENTRY, SDE_TO_PFSDE, DUMMY_IDX_ADJ, AFTERFREE_DUMMY); + } + break; + } + case kSDItemJump: + MERGE_JUMPS(wms->jumps_size, wms->jumps, PossiblyFreedShadaEntry, + data.timestamp, data.data.filemark.mark, entry, + strcmp(jl_entry.data.data.filemark.fname, + entry.data.filemark.fname) == 0, + FREE_POSSIBLY_FREED_SHADA_ENTRY, SDE_TO_PFSDE, + DUMMY_IDX_ADJ, AFTERFREE_DUMMY); #undef FREE_POSSIBLY_FREED_SHADA_ENTRY #undef SDE_TO_PFSDE #undef DUMMY_IDX_ADJ #undef AFTERFREE_DUMMY - break; - } + break; } } #undef COMPARE_WITH_ENTRY @@ -2372,8 +2300,7 @@ static inline ShaDaWriteResult shada_read_when_writing( /// @param[in] removable_bufs Cache of buffers ignored due to their location. /// /// @return true or false. -static inline bool ignore_buf(const buf_T *const buf, - khash_t(bufset) *const removable_bufs) +static inline bool ignore_buf(const buf_T *const buf, khash_t(bufset) *const removable_bufs) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { return (buf->b_ffname == NULL || !buf->b_p_bl || bt_quickfix(buf) \ @@ -2385,8 +2312,7 @@ static inline bool ignore_buf(const buf_T *const buf, /// @param[in] removable_bufs Buffers which are ignored /// /// @return ShadaEntry List of buffers to save, kSDItemBufferList entry. -static inline ShadaEntry shada_get_buflist( - khash_t(bufset) *const removable_bufs) +static inline ShadaEntry shada_get_buflist(khash_t(bufset) *const removable_bufs) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { int max_bufs = get_shada_parameter('%'); @@ -2400,14 +2326,14 @@ static inline ShadaEntry shada_get_buflist( ShadaEntry buflist_entry = (ShadaEntry) { .type = kSDItemBufferList, - .timestamp = os_time(), - .data = { - .buffer_list = { - .size = buf_count, - .buffers = xmalloc(buf_count - * sizeof(*buflist_entry.data.buffer_list.buffers)), - }, + .timestamp = os_time(), + .data = { + .buffer_list = { + .size = buf_count, + .buffers = xmalloc(buf_count + * sizeof(*buflist_entry.data.buffer_list.buffers)), }, + }, }; size_t i = 0; FOR_ALL_BUFFERS(buf) { @@ -2419,8 +2345,8 @@ static inline ShadaEntry shada_get_buflist( } buflist_entry.data.buffer_list.buffers[i] = (struct buffer_list_buffer) { .pos = buf->b_last_cursor.mark, - .fname = (char *)buf->b_ffname, - .additional_data = buf->additional_data, + .fname = (char *)buf->b_ffname, + .additional_data = buf->additional_data, }; i++; } @@ -2442,8 +2368,7 @@ static inline ShadaEntry shada_get_buflist( /// saved. static inline void add_search_pattern(PossiblyFreedShadaEntry *const ret_pse, const SearchPatternGetter get_pattern, - const bool is_substitute_pattern, - const bool search_last_used, + const bool is_substitute_pattern, const bool search_last_used, const bool search_highlighted) FUNC_ATTR_ALWAYS_INLINE { @@ -2464,7 +2389,7 @@ static inline void add_search_pattern(PossiblyFreedShadaEntry *const ret_pse, ? defaults.data.search_pattern.has_line_offset : pat.off.line), .place_cursor_at_end = ( - is_substitute_pattern + is_substitute_pattern ? defaults.data.search_pattern.place_cursor_at_end : pat.off.end), .offset = (is_substitute_pattern @@ -2488,8 +2413,7 @@ static inline void add_search_pattern(PossiblyFreedShadaEntry *const ret_pse, /// /// @param[in] wms The WriteMergerState used when writing. /// @param[in] max_reg_lines The maximum number of register lines. -static inline void shada_initialize_registers(WriteMergerState *const wms, - int max_reg_lines) +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; @@ -2534,8 +2458,7 @@ static inline void shada_initialize_registers(WriteMergerState *const wms, /// @param[out] wms Merger state to adjust. /// @param[in] idx Index at which new mark should be placed. /// @param[in] entry New mark. -static inline void replace_numbered_mark(WriteMergerState *const wms, - const size_t idx, +static inline void replace_numbered_mark(WriteMergerState *const wms, const size_t idx, const PossiblyFreedShadaEntry entry) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE { @@ -2573,8 +2496,7 @@ static inline void find_removable_bufs(khash_t(bufset) *removable_bufs) /// @param[in] sd_reader Structure containing file reader definition. If it is /// not NULL then contents of this file will be merged /// with current Neovim runtime. -static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, - ShaDaReadDef *const sd_reader) +static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef *const sd_reader) FUNC_ATTR_NONNULL_ARG(1) { ShaDaWriteResult ret = kSDWriteSuccessfull; @@ -2595,8 +2517,8 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, } const bool dump_registers = (max_reg_lines != 0); khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset); - const size_t max_kbyte = (size_t) max_kbyte_i; - const size_t num_marked_files = (size_t) get_shada_parameter('\''); + const size_t max_kbyte = (size_t)max_kbyte_i; + const size_t num_marked_files = (size_t)get_shada_parameter('\''); const bool dump_global_marks = get_shada_parameter('f') != 0; bool dump_history = false; @@ -2609,20 +2531,21 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, if (num_saved > 0) { dump_history = true; dump_one_history[i] = true; - hms_init(&wms->hms[i], i, (size_t) num_saved, sd_reader != NULL, false); + hms_init(&wms->hms[i], i, (size_t)num_saved, sd_reader != NULL, false); } else { dump_one_history[i] = false; } } - const unsigned srni_flags = (unsigned) ( - kSDReadUndisableableData - | kSDReadUnknown - | (dump_history ? kSDReadHistory : 0) - | (dump_registers ? kSDReadRegisters : 0) - | (dump_global_vars ? kSDReadVariables : 0) - | (dump_global_marks ? kSDReadGlobalMarks : 0) - | (num_marked_files ? kSDReadLocalMarks | kSDReadChanges : 0)); + const unsigned srni_flags = (unsigned)( + kSDReadUndisableableData + | kSDReadUnknown + | (dump_history ? kSDReadHistory : 0) + | (dump_registers ? kSDReadRegisters : 0) + | (dump_global_vars ? kSDReadVariables : 0) + | (dump_global_marks ? kSDReadGlobalMarks : 0) + | (num_marked_files ? kSDReadLocalMarks | + kSDReadChanges : 0)); msgpack_packer *const packer = msgpack_packer_new(sd_writer, &msgpack_sd_writer_write); @@ -2652,11 +2575,11 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, { STATIC_CSTR_AS_STRING("version"), STRING_OBJ(cstr_as_string(longVersion)) }, { STATIC_CSTR_AS_STRING("max_kbyte"), - INTEGER_OBJ((Integer) max_kbyte) }, + INTEGER_OBJ((Integer)max_kbyte) }, { STATIC_CSTR_AS_STRING("pid"), - INTEGER_OBJ((Integer) os_get_pid()) }, + INTEGER_OBJ((Integer)os_get_pid()) }, { STATIC_CSTR_AS_STRING("encoding"), - STRING_OBJ(cstr_as_string((char *) p_enc)) }, + STRING_OBJ(cstr_as_string((char *)p_enc)) }, }), } } @@ -2688,34 +2611,32 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, break; } switch (vartv.v_type) { - case VAR_FUNC: - case VAR_PARTIAL: + case VAR_FUNC: + case VAR_PARTIAL: + tv_clear(&vartv); + continue; + case VAR_DICT: { + dict_T *di = vartv.vval.v_dict; + int copyID = get_copyID(); + if (!set_ref_in_ht(&di->dv_hashtab, copyID, NULL) + && copyID == di->dv_copyID) { tv_clear(&vartv); continue; - case VAR_DICT: - { - dict_T *di = vartv.vval.v_dict; - int copyID = get_copyID(); - if (!set_ref_in_ht(&di->dv_hashtab, copyID, NULL) - && copyID == di->dv_copyID) { - tv_clear(&vartv); - continue; - } - break; - } - case VAR_LIST: - { - list_T *l = vartv.vval.v_list; - int copyID = get_copyID(); - if (!set_ref_in_list(l, copyID, NULL) - && copyID == l->lv_copyID) { - tv_clear(&vartv); - continue; - } - break; - } - default: - break; + } + break; + } + case VAR_LIST: { + list_T *l = vartv.vval.v_list; + int copyID = get_copyID(); + if (!set_ref_in_list(l, copyID, NULL) + && copyID == l->lv_copyID) { + tv_clear(&vartv); + continue; + } + break; + } + default: + break; } typval_T tgttv; tv_copy(&vartv, &tgttv); @@ -2725,7 +2646,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, .timestamp = cur_timestamp, .data = { .global_var = { - .name = (char *) name, + .name = (char *)name, .value = tgttv, .additional_elements = NULL, } @@ -2740,7 +2661,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, tv_clear(&tgttv); if (spe_ret == kSDWriteSuccessfull) { int kh_ret; - (void) kh_put(strset, &wms->dumped_variables, name, &kh_ret); + (void)kh_put(strset, &wms->dumped_variables, name, &kh_ret); } } while (var_iter != NULL); } @@ -2773,7 +2694,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, .timestamp = sub.timestamp, .data = { .sub_string = { - .sub = (char *) sub.sub, + .sub = (char *)sub.sub, .additional_elements = sub.additional_elements, } } @@ -2795,17 +2716,17 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, const char *fname; if (fm.fmark.fnum == 0) { assert(fm.fname != NULL); - if (shada_removable((const char *) fm.fname)) { + if (shada_removable((const char *)fm.fname)) { continue; } - fname = (const char *) fm.fname; + fname = (const char *)fm.fname; } else { const buf_T *const buf = buflist_findnr(fm.fmark.fnum); if (buf == NULL || buf->b_ffname == NULL || in_bufset(&removable_bufs, buf)) { continue; } - fname = (const char *) buf->b_ffname; + fname = (const char *)buf->b_ffname; } const PossiblyFreedShadaEntry pf_entry = { .can_free_entry = false, @@ -2842,7 +2763,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, continue; } const void *local_marks_iter = NULL; - const char *const fname = (const char *) buf->b_ffname; + const char *const fname = (const char *)buf->b_ffname; khiter_t k; int kh_ret; k = kh_put(file_marks, &wms->file_marks, fname, &kh_ret); @@ -2866,7 +2787,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, .filemark = { .mark = fm.mark, .name = name, - .fname = (char *) fname, + .fname = (char *)fname, .additional_data = fm.additional_data, } } @@ -2886,7 +2807,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, .data = { .filemark = { .mark = fm.mark, - .fname = (char *) fname, + .fname = (char *)fname, .additional_data = fm.additional_data, } } @@ -2896,13 +2817,13 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, filemarks->greatest_timestamp = fm.timestamp; } } - filemarks->changes_size = (size_t) buf->b_changelistlen; + filemarks->changes_size = (size_t)buf->b_changelistlen; } } if (sd_reader != NULL) { - const ShaDaWriteResult srww_ret = shada_read_when_writing( - sd_reader, srni_flags, max_kbyte, wms, packer); + const ShaDaWriteResult srww_ret = shada_read_when_writing(sd_reader, srni_flags, max_kbyte, wms, + packer); if (srww_ret != kSDWriteSuccessfull) { ret = srww_ret; } @@ -2968,7 +2889,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, const size_t file_markss_size = kh_size(&wms->file_marks); FileMarks **const all_file_markss = - xmalloc(file_markss_size * sizeof(*all_file_markss)); + xmalloc(file_markss_size * sizeof(*all_file_markss)); FileMarks **cur_file_marks = all_file_markss; for (khint_t i = kh_begin(&wms->file_marks); i != kh_end(&wms->file_marks); i++) { @@ -2976,7 +2897,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, *cur_file_marks++ = &kh_val(&wms->file_marks, i); } } - qsort((void *) all_file_markss, file_markss_size, sizeof(*all_file_markss), + qsort((void *)all_file_markss, file_markss_size, sizeof(*all_file_markss), &compare_file_marks); const size_t file_markss_to_dump = MIN(num_marked_files, file_markss_size); for (size_t i = 0; i < file_markss_to_dump; i++) { @@ -3007,11 +2928,10 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, if (dump_one_history[i]) { hms_insert_whole_neovim_history(&wms->hms[i]); HMS_ITER(&wms->hms[i], cur_entry, { - if (shada_pack_pfreed_entry( - packer, (PossiblyFreedShadaEntry) { - .data = cur_entry->data, - .can_free_entry = cur_entry->can_free_entry, - }, max_kbyte) == kSDWriteFailed) { + if (shada_pack_pfreed_entry(packer, (PossiblyFreedShadaEntry) { + .data = cur_entry->data, + .can_free_entry = cur_entry->can_free_entry, + }, max_kbyte) == kSDWriteFailed) { ret = kSDWriteFailed; break; } @@ -3082,7 +3002,7 @@ int shada_write_file(const char *const file, bool nomerge) } // Save permissions from the original file, with modifications: - int perm = (int) os_getperm(fname); + int perm = (int)os_getperm(fname); perm = (perm >= 0) ? ((perm & 0777) | 0600) : 0600; // ^3 ^1 ^2 ^2,3 // 1: Strip SUID bit if any. @@ -3090,8 +3010,7 @@ int shada_write_file(const char *const file, bool nomerge) // 3: If somebody happened to delete the file after it was opened for // reading use u=rw permissions. shada_write_file_open: {} - sd_writer.cookie = file_open_new( - &error, tempname, kFileCreateOnly|kFileNoSymlink, perm); + sd_writer.cookie = file_open_new(&error, tempname, kFileCreateOnly|kFileNoSymlink, perm); if (sd_writer.cookie == NULL) { if (error == UV_EEXIST || error == UV_ELOOP) { // File already exists, try another name @@ -3244,8 +3163,7 @@ int shada_read_marks(void) /// @param[in] missing_ok If true, do not error out when file is missing. /// /// @return OK in case of success, FAIL otherwise. -int shada_read_everything(const char *const fname, const bool forceit, - const bool missing_ok) +int shada_read_everything(const char *const fname, const bool forceit, const bool missing_ok) { return shada_read_file(fname, kShaDaWantInfo|kShaDaWantMarks|kShaDaGetOldfiles @@ -3259,62 +3177,52 @@ static void shada_free_shada_entry(ShadaEntry *const entry) return; } switch (entry->type) { - case kSDItemMissing: { - break; + case kSDItemMissing: + break; + case kSDItemUnknown: + xfree(entry->data.unknown_item.contents); + break; + case kSDItemHeader: + api_free_dictionary(entry->data.header); + break; + case kSDItemChange: + case kSDItemJump: + case kSDItemGlobalMark: + case kSDItemLocalMark: + tv_dict_unref(entry->data.filemark.additional_data); + xfree(entry->data.filemark.fname); + break; + case kSDItemSearchPattern: + tv_dict_unref(entry->data.search_pattern.additional_data); + xfree(entry->data.search_pattern.pat); + break; + case kSDItemRegister: + tv_dict_unref(entry->data.reg.additional_data); + for (size_t i = 0; i < entry->data.reg.contents_size; i++) { + xfree(entry->data.reg.contents[i]); } - case kSDItemUnknown: { - xfree(entry->data.unknown_item.contents); - break; - } - case kSDItemHeader: { - api_free_dictionary(entry->data.header); - break; - } - case kSDItemChange: - case kSDItemJump: - case kSDItemGlobalMark: - case kSDItemLocalMark: { - tv_dict_unref(entry->data.filemark.additional_data); - xfree(entry->data.filemark.fname); - break; - } - case kSDItemSearchPattern: { - tv_dict_unref(entry->data.search_pattern.additional_data); - xfree(entry->data.search_pattern.pat); - break; - } - case kSDItemRegister: { - tv_dict_unref(entry->data.reg.additional_data); - for (size_t i = 0; i < entry->data.reg.contents_size; i++) { - xfree(entry->data.reg.contents[i]); - } - xfree(entry->data.reg.contents); - break; - } - case kSDItemHistoryEntry: { - tv_list_unref(entry->data.history_item.additional_elements); - xfree(entry->data.history_item.string); - break; - } - case kSDItemVariable: { - tv_list_unref(entry->data.global_var.additional_elements); - xfree(entry->data.global_var.name); - tv_clear(&entry->data.global_var.value); - break; - } - case kSDItemSubString: { - tv_list_unref(entry->data.sub_string.additional_elements); - xfree(entry->data.sub_string.sub); - break; - } - case kSDItemBufferList: { - for (size_t i = 0; i < entry->data.buffer_list.size; i++) { - xfree(entry->data.buffer_list.buffers[i].fname); - tv_dict_unref(entry->data.buffer_list.buffers[i].additional_data); - } - xfree(entry->data.buffer_list.buffers); - break; + xfree(entry->data.reg.contents); + break; + case kSDItemHistoryEntry: + tv_list_unref(entry->data.history_item.additional_elements); + xfree(entry->data.history_item.string); + break; + case kSDItemVariable: + tv_list_unref(entry->data.global_var.additional_elements); + xfree(entry->data.global_var.name); + tv_clear(&entry->data.global_var.value); + break; + case kSDItemSubString: + tv_list_unref(entry->data.sub_string.additional_elements); + xfree(entry->data.sub_string.sub); + break; + case kSDItemBufferList: + for (size_t i = 0; i < entry->data.buffer_list.size; i++) { + xfree(entry->data.buffer_list.buffers[i].fname); + tv_dict_unref(entry->data.buffer_list.buffers[i].additional_data); } + xfree(entry->data.buffer_list.buffers); + break; } } @@ -3327,10 +3235,10 @@ static inline uint64_t be64toh(uint64_t big_endian_64_bits) // It may appear that when !defined(ORDER_BIG_ENDIAN) actual order is big // endian. This variant is suboptimal, but it works regardless of actual // order. - uint8_t *buf = (uint8_t *) &big_endian_64_bits; + uint8_t *buf = (uint8_t *)&big_endian_64_bits; uint64_t ret = 0; for (size_t i = 8; i; i--) { - ret |= ((uint64_t) buf[i - 1]) << ((8 - i) * 8); + ret |= ((uint64_t)buf[i - 1]) << ((8 - i) * 8); } return ret; #endif @@ -3346,8 +3254,7 @@ static inline uint64_t be64toh(uint64_t big_endian_64_bits) /// @return kSDReadStatusSuccess if everything was OK, kSDReadStatusNotShaDa if /// there were not enough bytes to read or kSDReadStatusReadError if /// there was some error while reading. -static ShaDaReadResult fread_len(ShaDaReadDef *const sd_reader, - char *const buffer, +static ShaDaReadResult fread_len(ShaDaReadDef *const sd_reader, char *const buffer, const size_t length) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { @@ -3385,8 +3292,7 @@ static ShaDaReadResult fread_len(ShaDaReadDef *const sd_reader, /// @return kSDReadStatusSuccess if reading was successful, /// kSDReadStatusNotShaDa if there were not enough bytes to read or /// kSDReadStatusReadError if reading failed for whatever reason. -static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, - const int first_char, +static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const int first_char, uint64_t *const result) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { @@ -3401,42 +3307,37 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, emsgf(_(RCERR "Error while reading ShaDa file: " "expected positive integer at position %" PRIu64 ", but got nothing"), - (uint64_t) fpos); + (uint64_t)fpos); return kSDReadStatusNotShaDa; } } if (~first_char & 0x80) { // Positive fixnum - *result = (uint64_t) ((uint8_t) first_char); + *result = (uint64_t)((uint8_t)first_char); } else { size_t length = 0; switch (first_char) { - case 0xCC: { // uint8 - length = 1; - break; - } - case 0xCD: { // uint16 - length = 2; - break; - } - case 0xCE: { // uint32 - length = 4; - break; - } - case 0xCF: { // uint64 - length = 8; - break; - } - default: { - emsgf(_(RCERR "Error while reading ShaDa file: " - "expected positive integer at position %" PRIu64), - (uint64_t) fpos); - return kSDReadStatusNotShaDa; - } + case 0xCC: // uint8 + length = 1; + break; + case 0xCD: // uint16 + length = 2; + break; + case 0xCE: // uint32 + length = 4; + break; + case 0xCF: // uint64 + length = 8; + break; + default: + emsgf(_(RCERR "Error while reading ShaDa file: " + "expected positive integer at position %" PRIu64), + (uint64_t)fpos); + return kSDReadStatusNotShaDa; } uint64_t buf = 0; - char *buf_u8 = (char *) &buf; + char *buf_u8 = (char *)&buf; ShaDaReadResult fl_ret; if ((fl_ret = fread_len(sd_reader, &(buf_u8[sizeof(buf)-length]), length)) != kSDReadStatusSuccess) { @@ -3448,24 +3349,24 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, } #define READERR(entry_name, error_desc) \ - RERR "Error while reading ShaDa file: " \ - entry_name " entry at position %" PRIu64 " " \ - error_desc + RERR "Error while reading ShaDa file: " \ + entry_name " entry at position %" PRIu64 " " \ + error_desc #define CHECK_KEY(key, expected) ( \ - key.via.str.size == sizeof(expected) - 1 \ - && STRNCMP(key.via.str.ptr, expected, sizeof(expected) - 1) == 0) + key.via.str.size == sizeof(expected) - 1 \ + && STRNCMP(key.via.str.ptr, expected, sizeof(expected) - 1) == 0) #define CLEAR_GA_AND_ERROR_OUT(ga) \ - do { \ - ga_clear(&ga); \ - goto shada_read_next_item_error; \ - } while (0) + do { \ + ga_clear(&ga); \ + goto shada_read_next_item_error; \ + } while (0) #define ID(s) s #define BINDUP(b) xmemdupz(b.ptr, b.size) -#define TOINT(s) ((int) (s)) -#define TOLONG(s) ((long) (s)) -#define TOCHAR(s) ((char) (s)) -#define TOU8(s) ((uint8_t) (s)) -#define TOSIZE(s) ((size_t) (s)) +#define TOINT(s) ((int)(s)) +#define TOLONG(s) ((long)(s)) +#define TOCHAR(s) ((char)(s)) +#define TOU8(s) ((uint8_t)(s)) +#define TOSIZE(s) ((size_t)(s)) #define CHECKED_ENTRY(condition, error_desc, entry_name, obj, tgt, attr, \ proc) \ do { \ @@ -3486,18 +3387,16 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, } #define CHECKED_KEY(un, entry_name, name, error_desc, tgt, condition, attr, \ proc) \ - else if (CHECK_KEY( /* NOLINT(readability/braces) */ \ - un.data.via.map.ptr[i].key, name)) { \ - CHECKED_ENTRY( \ - condition, "has " name " key value " error_desc, \ - entry_name, un.data.via.map.ptr[i].val, \ - tgt, attr, proc); \ + else if (CHECK_KEY( /* NOLINT(readability/braces) */ \ + un.data.via.map.ptr[i].key, name)) { \ + CHECKED_ENTRY(condition, "has " name " key value " error_desc, \ + entry_name, un.data.via.map.ptr[i].val, \ + tgt, attr, proc); \ } #define TYPED_KEY(un, entry_name, name, type_name, tgt, objtype, attr, proc) \ - CHECKED_KEY( \ - un, entry_name, name, "which is not " type_name, tgt, \ - un.data.via.map.ptr[i].val.type == MSGPACK_OBJECT_##objtype, \ - attr, proc) + CHECKED_KEY(un, entry_name, name, "which is not " type_name, tgt, \ + un.data.via.map.ptr[i].val.type == MSGPACK_OBJECT_##objtype, \ + attr, proc) #define BOOLEAN_KEY(un, entry_name, name, tgt) \ TYPED_KEY(un, entry_name, name, "a boolean", tgt, BOOLEAN, boolean, ID) #define STRING_KEY(un, entry_name, name, tgt) \ @@ -3506,19 +3405,18 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, TYPED_KEY(un, entry_name, name, "a binary", tgt, BIN, bin, \ BIN_CONVERTED) #define INT_KEY(un, entry_name, name, tgt, proc) \ - CHECKED_KEY( \ - un, entry_name, name, "which is not an integer", tgt, \ - ((un.data.via.map.ptr[i].val.type \ - == MSGPACK_OBJECT_POSITIVE_INTEGER) \ - || (un.data.via.map.ptr[i].val.type \ - == MSGPACK_OBJECT_NEGATIVE_INTEGER)), \ - i64, proc) + CHECKED_KEY(un, entry_name, name, "which is not an integer", tgt, \ + ((un.data.via.map.ptr[i].val.type \ + == MSGPACK_OBJECT_POSITIVE_INTEGER) \ + || (un.data.via.map.ptr[i].val.type \ + == MSGPACK_OBJECT_NEGATIVE_INTEGER)), \ + i64, proc) #define INTEGER_KEY(un, entry_name, name, tgt) \ INT_KEY(un, entry_name, name, tgt, TOINT) #define LONG_KEY(un, entry_name, name, tgt) \ INT_KEY(un, entry_name, name, tgt, TOLONG) #define ADDITIONAL_KEY(un) \ - else { /* NOLINT(readability/braces) */ \ + else { /* NOLINT(readability/braces) */ \ ga_grow(&ad_ga, 1); \ memcpy(((char *)ad_ga.ga_data) + ((size_t)ad_ga.ga_len \ * sizeof(*un.data.via.map.ptr)), \ @@ -3529,54 +3427,54 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, #define CONVERTED(str, len) (xmemdupz((str), (len))) #define BIN_CONVERTED(b) CONVERTED(b.ptr, b.size) #define SET_ADDITIONAL_DATA(tgt, name) \ - do { \ - if (ad_ga.ga_len) { \ - msgpack_object obj = { \ - .type = MSGPACK_OBJECT_MAP, \ - .via = { \ - .map = { \ - .size = (uint32_t) ad_ga.ga_len, \ - .ptr = ad_ga.ga_data, \ - } \ - } \ - }; \ - typval_T adtv; \ - if (msgpack_to_vim(obj, &adtv) == FAIL \ - || adtv.v_type != VAR_DICT) { \ - emsgf(_(READERR(name, \ - "cannot be converted to a VimL dictionary")), \ - initial_fpos); \ - ga_clear(&ad_ga); \ - tv_clear(&adtv); \ - goto shada_read_next_item_error; \ + do { \ + if (ad_ga.ga_len) { \ + msgpack_object obj = { \ + .type = MSGPACK_OBJECT_MAP, \ + .via = { \ + .map = { \ + .size = (uint32_t)ad_ga.ga_len, \ + .ptr = ad_ga.ga_data, \ } \ - tgt = adtv.vval.v_dict; \ } \ + }; \ + typval_T adtv; \ + if (msgpack_to_vim(obj, &adtv) == FAIL \ + || adtv.v_type != VAR_DICT) { \ + emsgf(_(READERR(name, \ + "cannot be converted to a VimL dictionary")), \ + initial_fpos); \ ga_clear(&ad_ga); \ - } while (0) + tv_clear(&adtv); \ + goto shada_read_next_item_error; \ + } \ + tgt = adtv.vval.v_dict; \ + } \ + ga_clear(&ad_ga); \ + } while (0) #define SET_ADDITIONAL_ELEMENTS(src, src_maxsize, tgt, name) \ - do { \ - if ((src).size > (size_t) (src_maxsize)) { \ - msgpack_object obj = { \ - .type = MSGPACK_OBJECT_ARRAY, \ - .via = { \ - .array = { \ - .size = ((src).size - (uint32_t) (src_maxsize)), \ - .ptr = (src).ptr + (src_maxsize), \ - } \ - } \ - }; \ - typval_T aetv; \ - if (msgpack_to_vim(obj, &aetv) == FAIL) { \ - emsgf(_(READERR(name, "cannot be converted to a VimL list")), \ - initial_fpos); \ - tv_clear(&aetv); \ - goto shada_read_next_item_error; \ + do { \ + if ((src).size > (size_t)(src_maxsize)) { \ + msgpack_object obj = { \ + .type = MSGPACK_OBJECT_ARRAY, \ + .via = { \ + .array = { \ + .size = ((src).size - (uint32_t)(src_maxsize)), \ + .ptr = (src).ptr + (src_maxsize), \ } \ - assert(aetv.v_type == VAR_LIST); \ - (tgt) = aetv.vval.v_list; \ } \ - } while (0) + }; \ + typval_T aetv; \ + if (msgpack_to_vim(obj, &aetv) == FAIL) { \ + emsgf(_(READERR(name, "cannot be converted to a VimL list")), \ + initial_fpos); \ + tv_clear(&aetv); \ + goto shada_read_next_item_error; \ + } \ + assert(aetv.v_type == VAR_LIST); \ + (tgt) = aetv.vval.v_list; \ + } \ + } while (0) /// Iterate over shada file contents /// @@ -3588,10 +3486,8 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, /// greater then given. /// /// @return Any value from ShaDaReadResult enum. -static ShaDaReadResult shada_read_next_item(ShaDaReadDef *const sd_reader, - ShadaEntry *const entry, - const unsigned flags, - const size_t max_kbyte) +static ShaDaReadResult shada_read_next_item(ShaDaReadDef *const sd_reader, ShadaEntry *const entry, + const unsigned flags, const size_t max_kbyte) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { ShaDaReadResult ret = kSDReadStatusMalformed; @@ -3607,11 +3503,11 @@ shada_read_next_item_start: // First: manually unpack type, timestamp and length. // This is needed to avoid both seeking and having to maintain a buffer. - uint64_t type_u64 = (uint64_t) kSDItemMissing; + uint64_t type_u64 = (uint64_t)kSDItemMissing; uint64_t timestamp_u64; uint64_t length_u64; - const uint64_t initial_fpos = (uint64_t) sd_reader->fpos; + const uint64_t initial_fpos = (uint64_t)sd_reader->fpos; const int first_char = read_char(sd_reader); if (first_char == EOF && sd_reader->eof) { return kSDReadStatusFinished; @@ -3654,7 +3550,7 @@ shada_read_next_item_start: if ((type_u64 > SHADA_LAST_ENTRY ? !(flags & kSDReadUnknown) - : !((unsigned) (1 << type_u64) & flags)) + : !((unsigned)(1 << type_u64) & flags)) || (max_kbyte && length > max_kbyte * 1024)) { // First entry is unknown or equal to "\n" (10)? Most likely this means that // current file is not a ShaDa file because first item should normally be @@ -3682,16 +3578,16 @@ shada_read_next_item_start: entry->data.unknown_item.size = length; entry->data.unknown_item.type = type_u64; if (initial_fpos == 0) { - const ShaDaReadResult spm_ret = shada_parse_msgpack( - sd_reader, length, NULL, &entry->data.unknown_item.contents); + const ShaDaReadResult spm_ret = shada_parse_msgpack(sd_reader, length, NULL, + &entry->data.unknown_item.contents); if (spm_ret != kSDReadStatusSuccess) { entry->type = kSDItemMissing; } return spm_ret; } else { entry->data.unknown_item.contents = xmalloc(length); - const ShaDaReadResult fl_ret = fread_len( - sd_reader, entry->data.unknown_item.contents, length); + const ShaDaReadResult fl_ret = + fread_len(sd_reader, entry->data.unknown_item.contents, length); if (fl_ret != kSDReadStatusSuccess) { shada_free_shada_entry(entry); entry->type = kSDItemMissing; @@ -3711,373 +3607,367 @@ shada_read_next_item_start: } ret = kSDReadStatusMalformed; entry->data = sd_default_values[type_u64].data; - switch ((ShadaEntryType) type_u64) { - case kSDItemHeader: { - if (!msgpack_rpc_to_dictionary(&(unpacked.data), &(entry->data.header))) { - emsgf(_(READERR("header", "is not a dictionary")), initial_fpos); - goto shada_read_next_item_error; - } - break; + switch ((ShadaEntryType)type_u64) { + case kSDItemHeader: + if (!msgpack_rpc_to_dictionary(&(unpacked.data), &(entry->data.header))) { + emsgf(_(READERR("header", "is not a dictionary")), initial_fpos); + goto shada_read_next_item_error; } - case kSDItemSearchPattern: { - if (unpacked.data.type != MSGPACK_OBJECT_MAP) { - emsgf(_(READERR("search pattern", "is not a dictionary")), - initial_fpos); - goto shada_read_next_item_error; - } - garray_T ad_ga; - ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1); - for (size_t i = 0; i < unpacked.data.via.map.size; i++) { - CHECK_KEY_IS_STR(unpacked, "search pattern") - BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_MAGIC, - entry->data.search_pattern.magic) - BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_SMARTCASE, - entry->data.search_pattern.smartcase) - BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_HAS_LINE_OFFSET, - entry->data.search_pattern.has_line_offset) - BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_PLACE_CURSOR_AT_END, - entry->data.search_pattern.place_cursor_at_end) - BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_IS_LAST_USED, - entry->data.search_pattern.is_last_used) - BOOLEAN_KEY(unpacked, "search pattern", - SEARCH_KEY_IS_SUBSTITUTE_PATTERN, - entry->data.search_pattern.is_substitute_pattern) - BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_HIGHLIGHTED, - entry->data.search_pattern.highlighted) - BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_BACKWARD, - entry->data.search_pattern.search_backward) - INTEGER_KEY(unpacked, "search pattern", SEARCH_KEY_OFFSET, - entry->data.search_pattern.offset) - CONVERTED_STRING_KEY(unpacked, "search pattern", SEARCH_KEY_PAT, - entry->data.search_pattern.pat) - ADDITIONAL_KEY(unpacked) - } - if (entry->data.search_pattern.pat == NULL) { - emsgf(_(READERR("search pattern", "has no pattern")), initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - SET_ADDITIONAL_DATA(entry->data.search_pattern.additional_data, - "search pattern"); - break; + break; + case kSDItemSearchPattern: { + if (unpacked.data.type != MSGPACK_OBJECT_MAP) { + emsgf(_(READERR("search pattern", "is not a dictionary")), + initial_fpos); + goto shada_read_next_item_error; } - case kSDItemChange: - case kSDItemJump: - case kSDItemGlobalMark: - case kSDItemLocalMark: { - if (unpacked.data.type != MSGPACK_OBJECT_MAP) { - emsgf(_(READERR("mark", "is not a dictionary")), initial_fpos); - goto shada_read_next_item_error; - } - garray_T ad_ga; - ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1); - for (size_t i = 0; i < unpacked.data.via.map.size; i++) { - CHECK_KEY_IS_STR(unpacked, "mark") - if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, KEY_NAME_CHAR)) { - if (type_u64 == kSDItemJump || type_u64 == kSDItemChange) { - emsgf(_(READERR("mark", "has n key which is only valid for " - "local and global mark entries")), initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - CHECKED_ENTRY( - (unpacked.data.via.map.ptr[i].val.type - == MSGPACK_OBJECT_POSITIVE_INTEGER), - "has n key value which is not an unsigned integer", - "mark", unpacked.data.via.map.ptr[i].val, - entry->data.filemark.name, u64, TOCHAR); + garray_T ad_ga; + ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1); + for (size_t i = 0; i < unpacked.data.via.map.size; i++) { + CHECK_KEY_IS_STR(unpacked, "search pattern") + BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_MAGIC, + entry->data.search_pattern.magic) + BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_SMARTCASE, + entry->data.search_pattern.smartcase) + BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_HAS_LINE_OFFSET, + entry->data.search_pattern.has_line_offset) + BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_PLACE_CURSOR_AT_END, + entry->data.search_pattern.place_cursor_at_end) + BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_IS_LAST_USED, + entry->data.search_pattern.is_last_used) + BOOLEAN_KEY(unpacked, "search pattern", + SEARCH_KEY_IS_SUBSTITUTE_PATTERN, + entry->data.search_pattern.is_substitute_pattern) + BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_HIGHLIGHTED, + entry->data.search_pattern.highlighted) + BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_BACKWARD, + entry->data.search_pattern.search_backward) + INTEGER_KEY(unpacked, "search pattern", SEARCH_KEY_OFFSET, + entry->data.search_pattern.offset) + CONVERTED_STRING_KEY(unpacked, "search pattern", SEARCH_KEY_PAT, + entry->data.search_pattern.pat) + ADDITIONAL_KEY(unpacked) + } + if (entry->data.search_pattern.pat == NULL) { + emsgf(_(READERR("search pattern", "has no pattern")), initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + SET_ADDITIONAL_DATA(entry->data.search_pattern.additional_data, + "search pattern"); + break; + } + case kSDItemChange: + case kSDItemJump: + case kSDItemGlobalMark: + case kSDItemLocalMark: { + if (unpacked.data.type != MSGPACK_OBJECT_MAP) { + emsgf(_(READERR("mark", "is not a dictionary")), initial_fpos); + goto shada_read_next_item_error; + } + garray_T ad_ga; + ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1); + for (size_t i = 0; i < unpacked.data.via.map.size; i++) { + CHECK_KEY_IS_STR(unpacked, "mark") + if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, KEY_NAME_CHAR)) { + if (type_u64 == kSDItemJump || type_u64 == kSDItemChange) { + emsgf(_(READERR("mark", "has n key which is only valid for " + "local and global mark entries")), initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); } - LONG_KEY(unpacked, "mark", KEY_LNUM, entry->data.filemark.mark.lnum) - INTEGER_KEY(unpacked, "mark", KEY_COL, entry->data.filemark.mark.col) - STRING_KEY(unpacked, "mark", KEY_FILE, entry->data.filemark.fname) - ADDITIONAL_KEY(unpacked) + CHECKED_ENTRY((unpacked.data.via.map.ptr[i].val.type + == MSGPACK_OBJECT_POSITIVE_INTEGER), + "has n key value which is not an unsigned integer", + "mark", unpacked.data.via.map.ptr[i].val, + entry->data.filemark.name, u64, TOCHAR); } - if (entry->data.filemark.fname == NULL) { - emsgf(_(READERR("mark", "is missing file name")), initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - if (entry->data.filemark.mark.lnum <= 0) { - emsgf(_(READERR("mark", "has invalid line number")), initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - if (entry->data.filemark.mark.col < 0) { - emsgf(_(READERR("mark", "has invalid column number")), initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - SET_ADDITIONAL_DATA(entry->data.filemark.additional_data, "mark"); - break; + LONG_KEY(unpacked, "mark", KEY_LNUM, entry->data.filemark.mark.lnum) + INTEGER_KEY(unpacked, "mark", KEY_COL, entry->data.filemark.mark.col) + STRING_KEY(unpacked, "mark", KEY_FILE, entry->data.filemark.fname) + ADDITIONAL_KEY(unpacked) } - case kSDItemRegister: { - if (unpacked.data.type != MSGPACK_OBJECT_MAP) { - emsgf(_(READERR("register", "is not a dictionary")), initial_fpos); - goto shada_read_next_item_error; - } - garray_T ad_ga; - ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1); - for (size_t i = 0; i < unpacked.data.via.map.size; i++) { - CHECK_KEY_IS_STR(unpacked, "register") - if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, - REG_KEY_CONTENTS)) { - if (unpacked.data.via.map.ptr[i].val.type != MSGPACK_OBJECT_ARRAY) { - emsgf(_(READERR("register", - "has " REG_KEY_CONTENTS - " key with non-array value")), - initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - if (unpacked.data.via.map.ptr[i].val.via.array.size == 0) { - emsgf(_(READERR("register", - "has " REG_KEY_CONTENTS " key with empty array")), - initial_fpos); + if (entry->data.filemark.fname == NULL) { + emsgf(_(READERR("mark", "is missing file name")), initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + if (entry->data.filemark.mark.lnum <= 0) { + emsgf(_(READERR("mark", "has invalid line number")), initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + if (entry->data.filemark.mark.col < 0) { + emsgf(_(READERR("mark", "has invalid column number")), initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + SET_ADDITIONAL_DATA(entry->data.filemark.additional_data, "mark"); + break; + } + case kSDItemRegister: { + if (unpacked.data.type != MSGPACK_OBJECT_MAP) { + emsgf(_(READERR("register", "is not a dictionary")), initial_fpos); + goto shada_read_next_item_error; + } + garray_T ad_ga; + ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1); + for (size_t i = 0; i < unpacked.data.via.map.size; i++) { + CHECK_KEY_IS_STR(unpacked, "register") + if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, + REG_KEY_CONTENTS)) { + if (unpacked.data.via.map.ptr[i].val.type != MSGPACK_OBJECT_ARRAY) { + emsgf(_(READERR("register", + "has " REG_KEY_CONTENTS + " key with non-array value")), + initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + if (unpacked.data.via.map.ptr[i].val.via.array.size == 0) { + emsgf(_(READERR("register", + "has " REG_KEY_CONTENTS " key with empty array")), + initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + const msgpack_object_array arr = + unpacked.data.via.map.ptr[i].val.via.array; + for (size_t j = 0; j < arr.size; j++) { + if (arr.ptr[j].type != MSGPACK_OBJECT_BIN) { + emsgf(_(READERR("register", "has " REG_KEY_CONTENTS " array " + "with non-binary value")), initial_fpos); CLEAR_GA_AND_ERROR_OUT(ad_ga); } - const msgpack_object_array arr = - unpacked.data.via.map.ptr[i].val.via.array; - for (size_t j = 0; j < arr.size; j++) { - if (arr.ptr[j].type != MSGPACK_OBJECT_BIN) { - emsgf(_(READERR("register", "has " REG_KEY_CONTENTS " array " - "with non-binary value")), initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - } - entry->data.reg.contents_size = arr.size; - entry->data.reg.contents = xmalloc(arr.size * sizeof(char *)); - for (size_t j = 0; j < arr.size; j++) { - entry->data.reg.contents[j] = BIN_CONVERTED(arr.ptr[j].via.bin); - } } - BOOLEAN_KEY(unpacked, "register", REG_KEY_UNNAMED, - entry->data.reg.is_unnamed) - TYPED_KEY(unpacked, "register", REG_KEY_TYPE, "an unsigned integer", - entry->data.reg.type, POSITIVE_INTEGER, u64, TOU8) - TYPED_KEY(unpacked, "register", KEY_NAME_CHAR, "an unsigned integer", - entry->data.reg.name, POSITIVE_INTEGER, u64, TOCHAR) - TYPED_KEY(unpacked, "register", REG_KEY_WIDTH, "an unsigned integer", - entry->data.reg.width, POSITIVE_INTEGER, u64, TOSIZE) - ADDITIONAL_KEY(unpacked) - } - if (entry->data.reg.contents == NULL) { - emsgf(_(READERR("register", "has missing " REG_KEY_CONTENTS " array")), - initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); + entry->data.reg.contents_size = arr.size; + entry->data.reg.contents = xmalloc(arr.size * sizeof(char *)); + for (size_t j = 0; j < arr.size; j++) { + entry->data.reg.contents[j] = BIN_CONVERTED(arr.ptr[j].via.bin); + } } - SET_ADDITIONAL_DATA(entry->data.reg.additional_data, "register"); - break; + BOOLEAN_KEY(unpacked, "register", REG_KEY_UNNAMED, + entry->data.reg.is_unnamed) + TYPED_KEY(unpacked, "register", REG_KEY_TYPE, "an unsigned integer", + entry->data.reg.type, POSITIVE_INTEGER, u64, TOU8) + TYPED_KEY(unpacked, "register", KEY_NAME_CHAR, "an unsigned integer", + entry->data.reg.name, POSITIVE_INTEGER, u64, TOCHAR) + TYPED_KEY(unpacked, "register", REG_KEY_WIDTH, "an unsigned integer", + entry->data.reg.width, POSITIVE_INTEGER, u64, TOSIZE) + ADDITIONAL_KEY(unpacked) } - case kSDItemHistoryEntry: { - if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { - emsgf(_(READERR("history", "is not an array")), initial_fpos); - goto shada_read_next_item_error; - } - if (unpacked.data.via.array.size < 2) { - emsgf(_(READERR("history", "does not have enough elements")), - initial_fpos); + if (entry->data.reg.contents == NULL) { + emsgf(_(READERR("register", "has missing " REG_KEY_CONTENTS " array")), + initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + SET_ADDITIONAL_DATA(entry->data.reg.additional_data, "register"); + break; + } + case kSDItemHistoryEntry: { + if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { + emsgf(_(READERR("history", "is not an array")), initial_fpos); + goto shada_read_next_item_error; + } + if (unpacked.data.via.array.size < 2) { + emsgf(_(READERR("history", "does not have enough elements")), + initial_fpos); + goto shada_read_next_item_error; + } + if (unpacked.data.via.array.ptr[0].type + != MSGPACK_OBJECT_POSITIVE_INTEGER) { + emsgf(_(READERR("history", "has wrong history type type")), + initial_fpos); + goto shada_read_next_item_error; + } + if (unpacked.data.via.array.ptr[1].type + != MSGPACK_OBJECT_BIN) { + emsgf(_(READERR("history", "has wrong history string type")), + initial_fpos); + goto shada_read_next_item_error; + } + if (memchr(unpacked.data.via.array.ptr[1].via.bin.ptr, 0, + unpacked.data.via.array.ptr[1].via.bin.size) != NULL) { + emsgf(_(READERR("history", "contains string with zero byte inside")), + initial_fpos); + goto shada_read_next_item_error; + } + entry->data.history_item.histtype = + (uint8_t)unpacked.data.via.array.ptr[0].via.u64; + const bool is_hist_search = + entry->data.history_item.histtype == HIST_SEARCH; + if (is_hist_search) { + if (unpacked.data.via.array.size < 3) { + emsgf(_(READERR("search history", + "does not have separator character")), initial_fpos); goto shada_read_next_item_error; } - if (unpacked.data.via.array.ptr[0].type + if (unpacked.data.via.array.ptr[2].type != MSGPACK_OBJECT_POSITIVE_INTEGER) { - emsgf(_(READERR("history", "has wrong history type type")), - initial_fpos); - goto shada_read_next_item_error; - } - if (unpacked.data.via.array.ptr[1].type - != MSGPACK_OBJECT_BIN) { - emsgf(_(READERR("history", "has wrong history string type")), - initial_fpos); + emsgf(_(READERR("search history", + "has wrong history separator type")), initial_fpos); goto shada_read_next_item_error; } - if (memchr(unpacked.data.via.array.ptr[1].via.bin.ptr, 0, - unpacked.data.via.array.ptr[1].via.bin.size) != NULL) { - emsgf(_(READERR("history", "contains string with zero byte inside")), - initial_fpos); - goto shada_read_next_item_error; - } - entry->data.history_item.histtype = - (uint8_t) unpacked.data.via.array.ptr[0].via.u64; - const bool is_hist_search = - entry->data.history_item.histtype == HIST_SEARCH; - if (is_hist_search) { - if (unpacked.data.via.array.size < 3) { - emsgf(_(READERR("search history", - "does not have separator character")), initial_fpos); - goto shada_read_next_item_error; - } - if (unpacked.data.via.array.ptr[2].type - != MSGPACK_OBJECT_POSITIVE_INTEGER) { - emsgf(_(READERR("search history", - "has wrong history separator type")), initial_fpos); + entry->data.history_item.sep = + (char)unpacked.data.via.array.ptr[2].via.u64; + } + size_t strsize; + strsize = ( + unpacked.data.via.array.ptr[1].via.bin.size + + 1 // Zero byte + + 1); // Separator character + entry->data.history_item.string = xmalloc(strsize); + memcpy(entry->data.history_item.string, + unpacked.data.via.array.ptr[1].via.bin.ptr, + unpacked.data.via.array.ptr[1].via.bin.size); + entry->data.history_item.string[strsize - 2] = 0; + entry->data.history_item.string[strsize - 1] = + entry->data.history_item.sep; + SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, (2 + is_hist_search), + entry->data.history_item.additional_elements, + "history"); + break; + } + case kSDItemVariable: { + if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { + emsgf(_(READERR("variable", "is not an array")), initial_fpos); + goto shada_read_next_item_error; + } + if (unpacked.data.via.array.size < 2) { + emsgf(_(READERR("variable", "does not have enough elements")), + initial_fpos); + goto shada_read_next_item_error; + } + if (unpacked.data.via.array.ptr[0].type != MSGPACK_OBJECT_BIN) { + emsgf(_(READERR("variable", "has wrong variable name type")), + initial_fpos); + goto shada_read_next_item_error; + } + entry->data.global_var.name = + xmemdupz(unpacked.data.via.array.ptr[0].via.bin.ptr, + unpacked.data.via.array.ptr[0].via.bin.size); + SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, 2, + entry->data.global_var.additional_elements, + "variable"); + bool is_blob = false; + // A msgpack BIN could be a String or Blob; an additional VAR_TYPE_BLOB + // element is stored with Blobs which can be used to differentiate them + if (unpacked.data.via.array.ptr[1].type == MSGPACK_OBJECT_BIN) { + const listitem_T *type_item + = tv_list_first(entry->data.global_var.additional_elements); + if (type_item != NULL) { + const typval_T *type_tv = TV_LIST_ITEM_TV(type_item); + if (type_tv->v_type != VAR_NUMBER + || type_tv->vval.v_number != VAR_TYPE_BLOB) { + emsgf(_(READERR("variable", "has wrong variable type")), + initial_fpos); goto shada_read_next_item_error; } - entry->data.history_item.sep = - (char) unpacked.data.via.array.ptr[2].via.u64; + is_blob = true; } - size_t strsize; - strsize = ( - unpacked.data.via.array.ptr[1].via.bin.size - + 1 // Zero byte - + 1); // Separator character - entry->data.history_item.string = xmalloc(strsize); - memcpy(entry->data.history_item.string, - unpacked.data.via.array.ptr[1].via.bin.ptr, - unpacked.data.via.array.ptr[1].via.bin.size); - entry->data.history_item.string[strsize - 2] = 0; - entry->data.history_item.string[strsize - 1] = - entry->data.history_item.sep; - SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, (2 + is_hist_search), - entry->data.history_item.additional_elements, - "history"); - break; } - case kSDItemVariable: { - if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { - emsgf(_(READERR("variable", "is not an array")), initial_fpos); - goto shada_read_next_item_error; - } - if (unpacked.data.via.array.size < 2) { - emsgf(_(READERR("variable", "does not have enough elements")), - initial_fpos); - goto shada_read_next_item_error; - } - if (unpacked.data.via.array.ptr[0].type != MSGPACK_OBJECT_BIN) { - emsgf(_(READERR("variable", "has wrong variable name type")), - initial_fpos); - goto shada_read_next_item_error; - } - entry->data.global_var.name = - xmemdupz(unpacked.data.via.array.ptr[0].via.bin.ptr, - unpacked.data.via.array.ptr[0].via.bin.size); - SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, 2, - entry->data.global_var.additional_elements, - "variable"); - bool is_blob = false; - // A msgpack BIN could be a String or Blob; an additional VAR_TYPE_BLOB - // element is stored with Blobs which can be used to differentiate them - if (unpacked.data.via.array.ptr[1].type == MSGPACK_OBJECT_BIN) { - const listitem_T *type_item - = tv_list_first(entry->data.global_var.additional_elements); - if (type_item != NULL) { - const typval_T *type_tv = TV_LIST_ITEM_TV(type_item); - if (type_tv->v_type != VAR_NUMBER - || type_tv->vval.v_number != VAR_TYPE_BLOB) { - emsgf(_(READERR("variable", "has wrong variable type")), - initial_fpos); - goto shada_read_next_item_error; - } - is_blob = true; - } - } - if (is_blob) { - const msgpack_object_bin *const bin - = &unpacked.data.via.array.ptr[1].via.bin; - blob_T *const blob = tv_blob_alloc(); - ga_concat_len(&blob->bv_ga, bin->ptr, (size_t)bin->size); - tv_blob_set_ret(&entry->data.global_var.value, blob); - } else if (msgpack_to_vim(unpacked.data.via.array.ptr[1], - &(entry->data.global_var.value)) == FAIL) { - emsgf(_(READERR("variable", "has value that cannot " - "be converted to the VimL value")), initial_fpos); - goto shada_read_next_item_error; - } - break; + if (is_blob) { + const msgpack_object_bin *const bin + = &unpacked.data.via.array.ptr[1].via.bin; + blob_T *const blob = tv_blob_alloc(); + ga_concat_len(&blob->bv_ga, bin->ptr, (size_t)bin->size); + tv_blob_set_ret(&entry->data.global_var.value, blob); + } else if (msgpack_to_vim(unpacked.data.via.array.ptr[1], + &(entry->data.global_var.value)) == FAIL) { + emsgf(_(READERR("variable", "has value that cannot " + "be converted to the VimL value")), initial_fpos); + goto shada_read_next_item_error; } - case kSDItemSubString: { - if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { - emsgf(_(READERR("sub string", "is not an array")), initial_fpos); - goto shada_read_next_item_error; - } - if (unpacked.data.via.array.size < 1) { - emsgf(_(READERR("sub string", "does not have enough elements")), - initial_fpos); - goto shada_read_next_item_error; - } - if (unpacked.data.via.array.ptr[0].type != MSGPACK_OBJECT_BIN) { - emsgf(_(READERR("sub string", "has wrong sub string type")), - initial_fpos); - goto shada_read_next_item_error; - } - entry->data.sub_string.sub = - BIN_CONVERTED(unpacked.data.via.array.ptr[0].via.bin); - SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, 1, - entry->data.sub_string.additional_elements, - "sub string"); + break; + } + case kSDItemSubString: + if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { + emsgf(_(READERR("sub string", "is not an array")), initial_fpos); + goto shada_read_next_item_error; + } + if (unpacked.data.via.array.size < 1) { + emsgf(_(READERR("sub string", "does not have enough elements")), + initial_fpos); + goto shada_read_next_item_error; + } + if (unpacked.data.via.array.ptr[0].type != MSGPACK_OBJECT_BIN) { + emsgf(_(READERR("sub string", "has wrong sub string type")), + initial_fpos); + goto shada_read_next_item_error; + } + entry->data.sub_string.sub = + BIN_CONVERTED(unpacked.data.via.array.ptr[0].via.bin); + SET_ADDITIONAL_ELEMENTS(unpacked.data.via.array, 1, + entry->data.sub_string.additional_elements, + "sub string"); + break; + case kSDItemBufferList: + if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { + emsgf(_(READERR("buffer list", "is not an array")), initial_fpos); + goto shada_read_next_item_error; + } + if (unpacked.data.via.array.size == 0) { break; } - case kSDItemBufferList: { - if (unpacked.data.type != MSGPACK_OBJECT_ARRAY) { - emsgf(_(READERR("buffer list", "is not an array")), initial_fpos); - goto shada_read_next_item_error; - } - if (unpacked.data.via.array.size == 0) { - break; - } - entry->data.buffer_list.buffers = - xcalloc(unpacked.data.via.array.size, - sizeof(*entry->data.buffer_list.buffers)); - for (size_t i = 0; i < unpacked.data.via.array.size; i++) { - entry->data.buffer_list.size++; - msgpack_unpacked unpacked_2 = (msgpack_unpacked) { - .data = unpacked.data.via.array.ptr[i], - }; + entry->data.buffer_list.buffers = + xcalloc(unpacked.data.via.array.size, + sizeof(*entry->data.buffer_list.buffers)); + for (size_t i = 0; i < unpacked.data.via.array.size; i++) { + entry->data.buffer_list.size++; + msgpack_unpacked unpacked_2 = (msgpack_unpacked) { + .data = unpacked.data.via.array.ptr[i], + }; + { + if (unpacked_2.data.type != MSGPACK_OBJECT_MAP) { + emsgf(_(RERR "Error while reading ShaDa file: " + "buffer list at position %" PRIu64 " " + "contains entry that is not a dictionary"), + initial_fpos); + goto shada_read_next_item_error; + } + entry->data.buffer_list.buffers[i].pos = default_pos; + garray_T ad_ga; + ga_init(&ad_ga, sizeof(*(unpacked_2.data.via.map.ptr)), 1); { - if (unpacked_2.data.type != MSGPACK_OBJECT_MAP) { - emsgf(_(RERR "Error while reading ShaDa file: " - "buffer list at position %" PRIu64 " " - "contains entry that is not a dictionary"), - initial_fpos); - goto shada_read_next_item_error; - } - entry->data.buffer_list.buffers[i].pos = default_pos; - garray_T ad_ga; - ga_init(&ad_ga, sizeof(*(unpacked_2.data.via.map.ptr)), 1); + // XXX: Temporarily reassign `i` because the macros depend on it. + const size_t j = i; { - // XXX: Temporarily reassign `i` because the macros depend on it. - const size_t j = i; - { - for (i = 0; i < unpacked_2.data.via.map.size; i++) { // -V535 - CHECK_KEY_IS_STR(unpacked_2, "buffer list entry") - LONG_KEY(unpacked_2, "buffer list entry", KEY_LNUM, - entry->data.buffer_list.buffers[j].pos.lnum) - INTEGER_KEY(unpacked_2, "buffer list entry", KEY_COL, - entry->data.buffer_list.buffers[j].pos.col) - STRING_KEY(unpacked_2, "buffer list entry", KEY_FILE, - entry->data.buffer_list.buffers[j].fname) - ADDITIONAL_KEY(unpacked_2) - } + for (i = 0; i < unpacked_2.data.via.map.size; i++) { // -V535 + CHECK_KEY_IS_STR(unpacked_2, "buffer list entry") + LONG_KEY(unpacked_2, "buffer list entry", KEY_LNUM, + entry->data.buffer_list.buffers[j].pos.lnum) + INTEGER_KEY(unpacked_2, "buffer list entry", KEY_COL, + entry->data.buffer_list.buffers[j].pos.col) + STRING_KEY(unpacked_2, "buffer list entry", KEY_FILE, + entry->data.buffer_list.buffers[j].fname) + ADDITIONAL_KEY(unpacked_2) } - i = j; // XXX: Restore `i`. } - if (entry->data.buffer_list.buffers[i].pos.lnum <= 0) { - emsgf(_(RERR "Error while reading ShaDa file: " - "buffer list at position %" PRIu64 " " - "contains entry with invalid line number"), - initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - if (entry->data.buffer_list.buffers[i].pos.col < 0) { - emsgf(_(RERR "Error while reading ShaDa file: " - "buffer list at position %" PRIu64 " " - "contains entry with invalid column number"), - initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - if (entry->data.buffer_list.buffers[i].fname == NULL) { - emsgf(_(RERR "Error while reading ShaDa file: " - "buffer list at position %" PRIu64 " " - "contains entry that does not have a file name"), - initial_fpos); - CLEAR_GA_AND_ERROR_OUT(ad_ga); - } - SET_ADDITIONAL_DATA( - entry->data.buffer_list.buffers[i].additional_data, - "buffer list entry"); + i = j; // XXX: Restore `i`. + } + if (entry->data.buffer_list.buffers[i].pos.lnum <= 0) { + emsgf(_(RERR "Error while reading ShaDa file: " + "buffer list at position %" PRIu64 " " + "contains entry with invalid line number"), + initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + if (entry->data.buffer_list.buffers[i].pos.col < 0) { + emsgf(_(RERR "Error while reading ShaDa file: " + "buffer list at position %" PRIu64 " " + "contains entry with invalid column number"), + initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); } + if (entry->data.buffer_list.buffers[i].fname == NULL) { + emsgf(_(RERR "Error while reading ShaDa file: " + "buffer list at position %" PRIu64 " " + "contains entry that does not have a file name"), + initial_fpos); + CLEAR_GA_AND_ERROR_OUT(ad_ga); + } + SET_ADDITIONAL_DATA(entry->data.buffer_list.buffers[i].additional_data, + "buffer list entry"); } - break; - } - case kSDItemMissing: - case kSDItemUnknown: { - abort(); } + break; + case kSDItemMissing: + case kSDItemUnknown: + abort(); } - entry->type = (ShadaEntryType) type_u64; + entry->type = (ShadaEntryType)type_u64; ret = kSDReadStatusSuccess; shada_read_next_item_end: if (buf != NULL) { @@ -4086,7 +3976,7 @@ shada_read_next_item_end: } return ret; shada_read_next_item_error: - entry->type = (ShadaEntryType) type_u64; + entry->type = (ShadaEntryType)type_u64; shada_free_shada_entry(entry); entry->type = kSDItemMissing; goto shada_read_next_item_end; @@ -4121,13 +4011,13 @@ shada_read_next_item_error: static bool shada_removable(const char *name) FUNC_ATTR_WARN_UNUSED_RESULT { - char *p; + char *p; char part[MAXPATHL + 1]; bool retval = false; char *new_name = home_replace_save(NULL, name); - for (p = (char *) p_shada; *p; ) { - (void) copy_option_part(&p, part, ARRAY_SIZE(part), ", "); + for (p = (char *)p_shada; *p; ) { + (void)copy_option_part(&p, part, ARRAY_SIZE(part), ", "); if (part[0] == 'r') { home_replace(NULL, part + 1, NameBuff, MAXPATHL, true); size_t n = STRLEN(NameBuff); @@ -4148,8 +4038,8 @@ static bool shada_removable(const char *name) /// location. /// /// @return number of jumplist entries -static inline size_t shada_init_jumps( - PossiblyFreedShadaEntry *jumps, khash_t(bufset) *const removable_bufs) +static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps, + khash_t(bufset) *const removable_bufs) { if (!curwin->w_jumplistlen) { return 0; @@ -4176,9 +4066,9 @@ static inline size_t shada_init_jumps( : fm.fmark.fnum != 0) { continue; } - const char *const fname = (char *) (fm.fmark.fnum == 0 + const char *const fname = (char *)(fm.fmark.fnum == 0 ? (fm.fname == NULL ? NULL : fm.fname) - : buf ? buf->b_ffname : NULL); + : buf ? buf->b_ffname : NULL); if (fname == NULL) { continue; } @@ -4191,7 +4081,7 @@ static inline size_t shada_init_jumps( .filemark = { .name = NUL, .mark = fm.fmark.mark, - .fname = (char *) fname, + .fname = (char *)fname, .additional_data = fm.fmark.additional_data, } } @@ -4272,9 +4162,8 @@ void shada_encode_gvars(msgpack_sbuffer *const sbuf) do { typval_T vartv; const char *name = NULL; - var_iter = var_shada_iter( - var_iter, &name, &vartv, - VAR_FLAVOUR_DEFAULT | VAR_FLAVOUR_SESSION | VAR_FLAVOUR_SHADA); + var_iter = var_shada_iter(var_iter, &name, &vartv, + VAR_FLAVOUR_DEFAULT | VAR_FLAVOUR_SESSION | VAR_FLAVOUR_SHADA); if (name == NULL) { break; } @@ -4304,8 +4193,7 @@ void shada_encode_gvars(msgpack_sbuffer *const sbuf) /// Wrapper for reading from msgpack_sbuffer. /// /// @return number of bytes read. -static ptrdiff_t read_sbuf(ShaDaReadDef *const sd_reader, void *const dest, - const size_t size) +static ptrdiff_t read_sbuf(ShaDaReadDef *const sd_reader, void *const dest, const size_t size) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { msgpack_sbuffer *sbuf = (msgpack_sbuffer *)sd_reader->cookie; @@ -4327,8 +4215,7 @@ static ptrdiff_t read_sbuf(ShaDaReadDef *const sd_reader, void *const dest, /// /// @return FAIL in case of failure, OK in case of success. May set /// sd_reader->eof. -static int sd_sbuf_reader_skip_read(ShaDaReadDef *const sd_reader, - const size_t offset) +static int sd_sbuf_reader_skip_read(ShaDaReadDef *const sd_reader, const size_t offset) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { msgpack_sbuffer *sbuf = (msgpack_sbuffer *)sd_reader->cookie; @@ -4346,8 +4233,7 @@ static int sd_sbuf_reader_skip_read(ShaDaReadDef *const sd_reader, /// /// @param[in] sbuf msgpack_sbuffer to read from. /// @param[out] sd_reader Location where reader structure will be saved. -static void open_shada_sbuf_for_reading(const msgpack_sbuffer *const sbuf, - ShaDaReadDef *sd_reader) +static void open_shada_sbuf_for_reading(const msgpack_sbuffer *const sbuf, ShaDaReadDef *sd_reader) FUNC_ATTR_NONNULL_ALL { *sd_reader = (ShaDaReadDef) { diff --git a/src/nvim/sign.c b/src/nvim/sign.c index c6f59b42b8..25427de6bf 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -6,33 +6,33 @@ // -#include "nvim/vim.h" -#include "nvim/sign.h" #include "nvim/ascii.h" #include "nvim/buffer.h" #include "nvim/charset.h" #include "nvim/cursor.h" -#include "nvim/ex_docmd.h" #include "nvim/edit.h" +#include "nvim/ex_docmd.h" #include "nvim/fold.h" #include "nvim/move.h" +#include "nvim/option.h" #include "nvim/screen.h" +#include "nvim/sign.h" #include "nvim/syntax.h" -#include "nvim/option.h" +#include "nvim/vim.h" /// Struct to hold the sign properties. typedef struct sign sign_T; struct sign { - 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 - int sn_line_hl; // highlight ID for line - int sn_text_hl; // highlight ID for text - int sn_num_hl; // highlight ID for line number + 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 + int sn_line_hl; // highlight ID for line + int sn_text_hl; // highlight ID for text + int sn_num_hl; // highlight ID for line number }; static sign_T *first_sign = NULL; @@ -42,19 +42,19 @@ static void sign_list_defined(sign_T *sp); static void sign_undefine(sign_T *sp, sign_T *sp_prev); static char *cmds[] = { - "define", + "define", #define SIGNCMD_DEFINE 0 - "undefine", + "undefine", #define SIGNCMD_UNDEFINE 1 - "list", + "list", #define SIGNCMD_LIST 2 - "place", + "place", #define SIGNCMD_PLACE 3 - "unplace", + "unplace", #define SIGNCMD_UNPLACE 4 - "jump", + "jump", #define SIGNCMD_JUMP 5 - NULL + NULL #define SIGNCMD_LAST 6 }; @@ -65,17 +65,17 @@ static int next_sign_id = 1; // next sign id in the global group /// Initialize data needed for managing signs void init_signs(void) { - hash_init(&sg_table); // sign group hash table + hash_init(&sg_table); // sign group hash table } /// 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_u *groupname) { - hash_T hash; - hashitem_T *hi; - signgroup_T *group; + hash_T hash; + hashitem_T *hi; + signgroup_T *group; hash = hash_hash(groupname); hi = hash_lookup(&sg_table, (char *)groupname, STRLEN(groupname), hash); @@ -100,7 +100,7 @@ static signgroup_T * sign_group_ref(const char_u *groupname) /// removed, then remove the group. static void sign_group_unref(char_u *groupname) { - hashitem_T *hi; + hashitem_T *hi; signgroup_T *group; hi = hash_find(&sg_table, groupname); @@ -120,10 +120,10 @@ static void sign_group_unref(char_u *groupname) /// or in a named group. If 'group' is '*', then the sign is part of the group. bool sign_in_group(sign_entry_T *sign, const char_u *group) { - 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)); + 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)); } /// Get the next free sign identifier in the specified group @@ -166,17 +166,19 @@ int sign_group_get_next_signid(buf_T *buf, const char_u *groupname) /// Insert a new sign into the signlist for buffer 'buf' between the 'prev' and /// 'next' signs. -static void insert_sign( - buf_T *buf, // buffer to store sign in - sign_entry_T *prev, // previous sign entry - sign_entry_T *next, // next sign entry - int id, // sign ID - const char_u *group, // sign group; NULL for global group - int prio, // sign priority - linenr_T lnum, // line number which gets the mark - int typenr, // typenr of sign we are adding - bool has_text_or_icon // sign has text or icon -) +/// +/// @param buf buffer to store sign in +/// @param prev previous sign entry +/// @param next next sign entry +/// @param id sign ID +/// @param group sign group; NULL for global group +/// @param prio sign priority +/// @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(buf_T *buf, sign_entry_T *prev, sign_entry_T *next, int id, + const char_u *group, int prio, linenr_T lnum, int typenr, + bool has_text_or_icon) { sign_entry_T *newsign = xmalloc(sizeof(sign_entry_T)); newsign->se_id = id; @@ -212,18 +214,19 @@ static void insert_sign( } /// Insert a new sign sorted by line number and sign priority. -static void insert_sign_by_lnum_prio( - buf_T *buf, // buffer to store sign in - sign_entry_T *prev, // previous sign entry - int id, // sign ID - const char_u *group, // sign group; NULL for global group - int prio, // sign priority - linenr_T lnum, // line number which gets the mark - int typenr, // typenr of sign we are adding - bool has_text_or_icon // sign has text or icon -) +/// +/// @param buf buffer to store sign in +/// @param prev previous sign entry +/// @param id sign ID +/// @param group sign group; NULL for global group +/// @param prio sign priority +/// @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, + int prio, linenr_T lnum, int typenr, bool has_text_or_icon) { - sign_entry_T *sign; + sign_entry_T *sign; // keep signs sorted by lnum, priority and id: insert new sign at // the proper position in the list for this lnum. @@ -242,9 +245,9 @@ static void insert_sign_by_lnum_prio( } /// Get the name of a sign by its typenr. -char_u * sign_typenr2name(int typenr) +char_u *sign_typenr2name(int typenr) { - sign_T *sp; + sign_T *sp; for (sp = first_sign; sp != NULL; sp = sp->sn_next) { if (sp->sn_typenr == typenr) { @@ -255,9 +258,9 @@ char_u * sign_typenr2name(int typenr) } /// Return information about a sign in a Dict -dict_T * sign_get_info(sign_entry_T *sign) +dict_T *sign_get_info(sign_entry_T *sign) { - dict_T *d = tv_dict_alloc(); + dict_T *d = tv_dict_alloc(); tv_dict_add_nr(d, S_LEN("id"), sign->se_id); tv_dict_add_str(d, S_LEN("group"), ((sign->se_group == NULL) ? (char *)"" @@ -345,15 +348,16 @@ static void sign_sort_by_prio_on_line(buf_T *buf, sign_entry_T *sign) /// Add the sign into the signlist. Find the right spot to do it though. -void buf_addsign( - buf_T *buf, // buffer to store sign in - int id, // sign ID - const char_u *groupname, // sign group - int prio, // sign priority - linenr_T lnum, // line number which gets the mark - int typenr, // typenr of sign we are adding - bool has_text_or_icon // sign has text or icon -) +/// +/// @param buf buffer to store sign in +/// @param id sign ID +/// @param groupname sign group +/// @param prio sign priority +/// @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 +void buf_addsign(buf_T *buf, int id, const char_u *groupname, int prio, linenr_T lnum, int typenr, + bool has_text_or_icon) { sign_entry_T *sign; // a sign in the signlist sign_entry_T *prev; // the previous sign @@ -368,53 +372,51 @@ void buf_addsign( sign_sort_by_prio_on_line(buf, sign); return; } else if (lnum < sign->se_lnum) { - insert_sign_by_lnum_prio( - buf, - prev, - id, - groupname, - prio, - lnum, - typenr, - has_text_or_icon); + insert_sign_by_lnum_prio(buf, + prev, + id, + groupname, + prio, + lnum, + typenr, + has_text_or_icon); return; } prev = sign; } - insert_sign_by_lnum_prio( - buf, - prev, - id, - groupname, - prio, - lnum, - typenr, - has_text_or_icon); + insert_sign_by_lnum_prio(buf, + prev, + id, + groupname, + prio, + lnum, + typenr, + has_text_or_icon); } -// For an existing, placed sign "markId" change the type to "typenr". -// Returns the line number of the sign, or zero if the sign is not found. -linenr_T buf_change_sign_type( - buf_T *buf, // buffer to store sign in - int markId, // sign ID - const char_u *group, // sign group - int typenr, // typenr of sign we are adding - int prio // sign priority -) +/// For an existing, placed sign "markId" change the type to "typenr". +/// Returns the line number of the sign, or zero if the sign is not found. +/// +/// @param buf buffer to store sign in +/// @param markId sign ID +/// @param group sign group +/// @param typenr typenr of sign we are adding +/// @param prio sign priority +linenr_T buf_change_sign_type(buf_T *buf, int markId, const char_u *group, int typenr, int prio) { - sign_entry_T *sign; // a sign in the signlist + 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)) { - sign->se_typenr = typenr; - sign->se_priority = prio; - sign_sort_by_prio_on_line(buf, sign); - return sign->se_lnum; - } + FOR_ALL_SIGNS_IN_BUF(buf, sign) { + if (sign->se_id == markId && sign_in_group(sign, group)) { + sign->se_typenr = typenr; + sign->se_priority = prio; + sign_sort_by_prio_on_line(buf, sign); + return sign->se_lnum; } + } - return (linenr_T)0; + return (linenr_T)0; } /// Return the sign attrs which has the attribute specified by 'type'. Returns @@ -426,44 +428,43 @@ linenr_T buf_change_sign_type( /// @param max_signs the number of signs, with priority for the ones /// with the highest Ids. /// @return Attrs of the matching sign, or NULL -sign_attrs_T * sign_get_attr(SignType type, sign_attrs_T sattrs[], - int idx, int max_signs) +sign_attrs_T *sign_get_attr(SignType type, sign_attrs_T sattrs[], int idx, int max_signs) { - sign_attrs_T *matches[SIGN_SHOW_MAX]; - int nr_matches = 0; - - for (int i = 0; i < SIGN_SHOW_MAX; i++) { - if ( (type == SIGN_TEXT && sattrs[i].sat_text != NULL) - || (type == SIGN_LINEHL && sattrs[i].sat_linehl != 0) - || (type == SIGN_NUMHL && sattrs[i].sat_numhl != 0)) { - matches[nr_matches] = &sattrs[i]; - nr_matches++; - // attr list is sorted with most important (priority, id), thus we - // may stop as soon as we have max_signs matches - if (nr_matches >= max_signs) { - break; - } - } + sign_attrs_T *matches[SIGN_SHOW_MAX]; + int nr_matches = 0; + + for (int i = 0; i < SIGN_SHOW_MAX; i++) { + if ( (type == SIGN_TEXT && sattrs[i].sat_text != NULL) + || (type == SIGN_LINEHL && sattrs[i].sat_linehl != 0) + || (type == SIGN_NUMHL && sattrs[i].sat_numhl != 0)) { + matches[nr_matches] = &sattrs[i]; + nr_matches++; + // attr list is sorted with most important (priority, id), thus we + // may stop as soon as we have max_signs matches + if (nr_matches >= max_signs) { + break; + } } + } - if (nr_matches > idx) { - return matches[nr_matches - idx - 1]; - } + if (nr_matches > idx) { + return matches[nr_matches - idx - 1]; + } - return NULL; + return NULL; } /// Lookup a sign by typenr. Returns NULL if sign is not found. -static sign_T * find_sign_by_typenr(int typenr) +static sign_T *find_sign_by_typenr(int typenr) { - sign_T *sp; + sign_T *sp; - for (sp = first_sign; sp != NULL; sp = sp->sn_next) { - if (sp->sn_typenr == typenr) { - return sp; - } + for (sp = first_sign; sp != NULL; sp = sp->sn_next) { + if (sp->sn_typenr == typenr) { + return sp; } - return NULL; + } + return NULL; } /// Return the attributes of all the signs placed on line 'lnum' in buffer @@ -474,44 +475,44 @@ static sign_T * find_sign_by_typenr(int typenr) /// @return Number of signs of which attrs were found int buf_get_signattrs(buf_T *buf, linenr_T lnum, sign_attrs_T sattrs[]) { - sign_entry_T *sign; - sign_T *sp; + sign_entry_T *sign; + sign_T *sp; - int nr_matches = 0; + int nr_matches = 0; - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (sign->se_lnum > lnum) { - // Signs are sorted by line number in the buffer. No need to check - // for signs after the specified line number 'lnum'. - break; - } + FOR_ALL_SIGNS_IN_BUF(buf, sign) { + if (sign->se_lnum > lnum) { + // Signs are sorted by line number in the buffer. No need to check + // for signs after the specified line number 'lnum'. + break; + } - if (sign->se_lnum == lnum) { - sign_attrs_T sattr; - memset(&sattr, 0, sizeof(sattr)); - sattr.sat_typenr = sign->se_typenr; - sp = find_sign_by_typenr(sign->se_typenr); - if (sp != NULL) { - sattr.sat_text = sp->sn_text; - if (sattr.sat_text != NULL && sp->sn_text_hl != 0) { - sattr.sat_texthl = syn_id2attr(sp->sn_text_hl); - } - if (sp->sn_line_hl != 0) { - sattr.sat_linehl = syn_id2attr(sp->sn_line_hl); - } - if (sp->sn_num_hl != 0) { - sattr.sat_numhl = syn_id2attr(sp->sn_num_hl); - } - } - - sattrs[nr_matches] = sattr; - nr_matches++; - if (nr_matches == SIGN_SHOW_MAX) { - break; - } + if (sign->se_lnum == lnum) { + sign_attrs_T sattr; + memset(&sattr, 0, sizeof(sattr)); + sattr.sat_typenr = sign->se_typenr; + sp = find_sign_by_typenr(sign->se_typenr); + if (sp != NULL) { + sattr.sat_text = sp->sn_text; + if (sattr.sat_text != NULL && sp->sn_text_hl != 0) { + sattr.sat_texthl = syn_id2attr(sp->sn_text_hl); + } + if (sp->sn_line_hl != 0) { + sattr.sat_linehl = syn_id2attr(sp->sn_line_hl); + } + if (sp->sn_num_hl != 0) { + sattr.sat_numhl = syn_id2attr(sp->sn_num_hl); } + } + + sattrs[nr_matches] = sattr; + nr_matches++; + if (nr_matches == SIGN_SHOW_MAX) { + break; + } } - return nr_matches; + } + return nr_matches; } /// Delete sign 'id' in group 'group' from buffer 'buf'. @@ -520,14 +521,15 @@ int buf_get_signattrs(buf_T *buf, linenr_T lnum, sign_attrs_T sattrs[]) /// If 'group' is '*', then delete the sign in all the groups. If 'group' is /// NULL, then delete the sign in the global group. Otherwise delete the sign in /// the specified group. -/// Returns the line number of the deleted sign. If multiple signs are deleted, +/// +/// @param buf buffer sign is stored in +/// @param atlnum sign at this line, 0 - at any line +/// @param id sign id +/// @param group sign group +/// +/// @return the line number of the deleted sign. If multiple signs are deleted, /// then returns the line number of the last sign deleted. -linenr_T buf_delsign( - buf_T *buf, // buffer sign is stored in - linenr_T atlnum, // sign at this line, 0 - at any line - int id, // sign id - char_u *group // sign group -) +linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char_u *group) { sign_entry_T **lastp; // pointer to pointer to current sign sign_entry_T *sign; // a sign in a b_signlist @@ -580,30 +582,30 @@ linenr_T buf_delsign( /// Find the line number of the sign with the requested id in group 'group'. If /// the sign does not exist, return 0 as the line number. This will still let /// the correct file get loaded. -int buf_findsign( - buf_T *buf, // buffer to store sign in - int id, // sign ID - char_u *group // sign group -) +/// +/// @param buf buffer to store sign in +/// @param id sign ID +/// @param group sign group +int buf_findsign(buf_T *buf, int id, char_u *group) { - sign_entry_T *sign; // a sign in the signlist + sign_entry_T *sign; // a sign in the signlist - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (sign->se_id == id && sign_in_group(sign, group)) { - return (int)sign->se_lnum; - } + FOR_ALL_SIGNS_IN_BUF(buf, sign) { + if (sign->se_id == id && sign_in_group(sign, group)) { + return (int)sign->se_lnum; } + } - return 0; + return 0; } /// Return the sign at line 'lnum' in buffer 'buf'. Returns NULL if a sign is /// not found at the line. If 'groupname' is NULL, searches in the global group. -static sign_entry_T * buf_getsign_at_line( - buf_T *buf, // buffer whose sign we are searching for - linenr_T lnum, // line number of sign - char_u *groupname // sign group name -) +/// +/// @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) { sign_entry_T *sign; // a sign in the signlist @@ -623,61 +625,61 @@ static sign_entry_T * buf_getsign_at_line( } /// Return the identifier of the sign at line number 'lnum' in buffer 'buf'. -int buf_findsign_id( - buf_T *buf, // buffer whose sign we are searching for - linenr_T lnum, // line number of sign - char_u *groupname // sign group name -) +/// +/// @param buf buffer whose sign we are searching for +/// @param lnum line number of sign +/// @param groupname sign group name +int buf_findsign_id(buf_T *buf, linenr_T lnum, char_u *groupname) { - sign_entry_T *sign; // a sign in the signlist + sign_entry_T *sign; // a sign in the signlist - sign = buf_getsign_at_line(buf, lnum, groupname); - if (sign != NULL) { - return sign->se_id; - } + sign = buf_getsign_at_line(buf, lnum, groupname); + if (sign != NULL) { + return sign->se_id; + } - return 0; + return 0; } /// Delete signs in buffer "buf". void buf_delete_signs(buf_T *buf, char_u *group) { - sign_entry_T *sign; - sign_entry_T **lastp; // pointer to pointer to current sign - sign_entry_T *next; + sign_entry_T *sign; + sign_entry_T **lastp; // pointer to pointer to current sign + sign_entry_T *next; - // When deleting the last sign need to redraw the windows to remove the - // sign column. Not when curwin is NULL (this means we're exiting). - if (buf->b_signlist != NULL && curwin != NULL) { - changed_line_abv_curs(); - } + // When deleting the last sign need to redraw the windows to remove the + // sign column. Not when curwin is NULL (this means we're exiting). + if (buf->b_signlist != NULL && curwin != NULL) { + changed_line_abv_curs(); + } - lastp = &buf->b_signlist; - for (sign = buf->b_signlist; sign != NULL; sign = next) { - next = sign->se_next; - 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); - } - xfree(sign); - } else { - lastp = &sign->se_next; + lastp = &buf->b_signlist; + for (sign = buf->b_signlist; sign != NULL; sign = next) { + next = sign->se_next; + 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); } + xfree(sign); + } else { + lastp = &sign->se_next; } - buf->b_signcols_valid = false; + } + buf->b_signcols_valid = false; } /// List placed signs for "rbuf". If "rbuf" is NULL do it for all buffers. void sign_list_placed(buf_T *rbuf, char_u *sign_group) { buf_T *buf; - sign_entry_T *sign; - char lbuf[MSG_BUF_LEN]; - char group[MSG_BUF_LEN]; + sign_entry_T *sign; + char lbuf[MSG_BUF_LEN]; + char group[MSG_BUF_LEN]; MSG_PUTS_TITLE(_("\n--- Signs ---")); msg_putchar('\n'); @@ -720,12 +722,7 @@ void sign_list_placed(buf_T *rbuf, char_u *sign_group) } /// Adjust a placed sign for inserted/deleted lines. -void sign_mark_adjust( - linenr_T line1, - linenr_T line2, - long amount, - long amount_after -) +void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after) { sign_entry_T *sign; // a sign in a b_signlist sign_entry_T *next; // the next sign in a b_signlist @@ -769,26 +766,26 @@ void sign_mark_adjust( /// Find index of a ":sign" subcmd from its name. /// "*end_cmd" must be writable. -static int sign_cmd_idx( - char_u *begin_cmd, // begin of sign subcmd - char_u *end_cmd // just after sign subcmd -) +/// +/// @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) { - int idx; - char_u save = *end_cmd; + int idx; + char_u save = *end_cmd; - *end_cmd = (char_u)NUL; - for (idx = 0; ; idx++) { - if (cmds[idx] == NULL || STRCMP(begin_cmd, cmds[idx]) == 0) { - break; - } + *end_cmd = (char_u)NUL; + for (idx = 0; ; idx++) { + if (cmds[idx] == NULL || STRCMP(begin_cmd, cmds[idx]) == 0) { + break; } - *end_cmd = save; - return idx; + } + *end_cmd = save; + return idx; } /// 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_u *name, sign_T **sp_prev) { sign_T *sp; @@ -808,10 +805,10 @@ 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_u *name) { - sign_T *sp; - sign_T *lp; + sign_T *sp; + sign_T *lp; int start = next_sign_typenr; // Allocate a new sign. @@ -858,8 +855,8 @@ static void sign_define_init_icon(sign_T *sp, char_u *icon) /// Initialize the text for a new sign static int sign_define_init_text(sign_T *sp, char_u *text) { - char_u *s; - char_u *endp; + char_u *s; + char_u *endp; int cells; size_t len; @@ -904,17 +901,11 @@ static int sign_define_init_text(sign_T *sp, char_u *text) } /// Define a new sign or update an existing sign -int sign_define_by_name( - char_u *name, - char_u *icon, - char_u *linehl, - char_u *text, - char_u *texthl, - char_u *numhl -) +int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl, + char_u *numhl) { - sign_T *sp_prev; - sign_T *sp; + sign_T *sp_prev; + sign_T *sp; sp = sign_find(name, &sp_prev); if (sp == NULL) { @@ -966,8 +957,8 @@ int sign_define_by_name( /// Free the sign specified by 'name'. int sign_undefine_by_name(const char_u *name) { - sign_T *sp_prev; - sign_T *sp; + sign_T *sp_prev; + sign_T *sp; sp = sign_find(name, &sp_prev); if (sp == NULL) { @@ -982,18 +973,18 @@ int sign_undefine_by_name(const char_u *name) static void may_force_numberwidth_recompute(buf_T *buf, int unplace) { FOR_ALL_TAB_WINDOWS(tp, wp) - if (wp->w_buffer == buf - && (wp->w_p_nu || wp->w_p_rnu) - && (unplace || wp->w_nrwidth_width < 2) - && (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')) { - wp->w_nrwidth_line_count = 0; - } + if (wp->w_buffer == buf + && (wp->w_p_nu || wp->w_p_rnu) + && (unplace || wp->w_nrwidth_width < 2) + && (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')) { + wp->w_nrwidth_line_count = 0; + } } /// List the signs matching 'name' static void sign_list_by_name(char_u *name) { - sign_T *sp; + sign_T *sp; sp = sign_find(name, NULL); if (sp != NULL) { @@ -1005,14 +996,8 @@ static void sign_list_by_name(char_u *name) /// Place a sign at the specified file location or update a sign. -int sign_place( - int *sign_id, - const char_u *sign_group, - const char_u *sign_name, - buf_T *buf, - linenr_T lnum, - int prio -) +int sign_place(int *sign_id, const char_u *sign_group, const char_u *sign_name, buf_T *buf, + linenr_T lnum, int prio) { sign_T *sp; @@ -1038,14 +1023,13 @@ int sign_place( // ":sign place {id} line={lnum} name={name} file={fname}": // place a sign bool has_text_or_icon = sp->sn_text != NULL || sp->sn_icon != NULL; - buf_addsign( - buf, - *sign_id, - sign_group, - prio, - lnum, - sp->sn_typenr, - has_text_or_icon); + buf_addsign(buf, + *sign_id, + 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); @@ -1075,7 +1059,7 @@ int sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T atlnum) redraw_buf_later(buf, NOT_VALID); buf_delete_signs(buf, sign_group); } else { - linenr_T lnum; + linenr_T lnum; // Delete only the specified signs lnum = buf_delsign(buf, atlnum, sign_id, sign_group); @@ -1098,7 +1082,7 @@ int sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T atlnum) /// Unplace the sign at the current cursor line. static void sign_unplace_at_cursor(char_u *groupname) { - int id = -1; + int id = -1; id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum, groupname); if (id > 0) { @@ -1144,13 +1128,13 @@ 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 *numhl = NULL; + 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 *numhl = NULL; int failed = false; // set values for a defined sign. @@ -1194,14 +1178,8 @@ 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, - int prio -) +static void sign_place_cmd(buf_T *buf, linenr_T lnum, char_u *sign_name, int id, char_u *group, + int prio) { if (id <= 0) { // List signs placed in a file/buffer @@ -1233,62 +1211,56 @@ static void sign_place_cmd( } /// ":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_u *sign_name, int id, char_u *group) { - if (lnum >= 0 || sign_name != NULL || (group != NULL && *group == '\0')) { - EMSG(_(e_invarg)); - return; - } + if (lnum >= 0 || sign_name != NULL || (group != NULL && *group == '\0')) { + EMSG(_(e_invarg)); + return; + } - if (id == -2) { - if (buf != NULL) { - // :sign unplace * file={fname} - // :sign unplace * group={group} file={fname} - // :sign unplace * group=* file={fname} - // :sign unplace * buffer={nr} - // :sign unplace * group={group} buffer={nr} - // :sign unplace * group=* buffer={nr} - sign_unplace(0, group, buf, 0); - } else { - // :sign unplace * - // :sign unplace * group={group} - // :sign unplace * group=* - FOR_ALL_BUFFERS(cbuf) { - if (cbuf->b_signlist != NULL) { - buf_delete_signs(cbuf, group); - } + if (id == -2) { + if (buf != NULL) { + // :sign unplace * file={fname} + // :sign unplace * group={group} file={fname} + // :sign unplace * group=* file={fname} + // :sign unplace * buffer={nr} + // :sign unplace * group={group} buffer={nr} + // :sign unplace * group=* buffer={nr} + sign_unplace(0, group, buf, 0); + } else { + // :sign unplace * + // :sign unplace * group={group} + // :sign unplace * group=* + FOR_ALL_BUFFERS(cbuf) { + if (cbuf->b_signlist != NULL) { + buf_delete_signs(cbuf, group); } } + } + } else { + if (buf != NULL) { + // :sign unplace {id} file={fname} + // :sign unplace {id} group={group} file={fname} + // :sign unplace {id} group=* file={fname} + // :sign unplace {id} buffer={nr} + // :sign unplace {id} group={group} buffer={nr} + // :sign unplace {id} group=* buffer={nr} + sign_unplace(id, group, buf, 0); } else { - if (buf != NULL) { - // :sign unplace {id} file={fname} - // :sign unplace {id} group={group} file={fname} - // :sign unplace {id} group=* file={fname} - // :sign unplace {id} buffer={nr} - // :sign unplace {id} group={group} buffer={nr} - // :sign unplace {id} group=* buffer={nr} - sign_unplace(id, group, buf, 0); + if (id == -1) { + // :sign unplace group={group} + // :sign unplace group=* + sign_unplace_at_cursor(group); } else { - if (id == -1) { - // :sign unplace group={group} - // :sign unplace group=* - sign_unplace_at_cursor(group); - } else { - // :sign unplace {id} - // :sign unplace {id} group={group} - // :sign unplace {id} group=* - FOR_ALL_BUFFERS(cbuf) { - sign_unplace(id, group, cbuf, 0); - } + // :sign unplace {id} + // :sign unplace {id} group={group} + // :sign unplace {id} group=* + FOR_ALL_BUFFERS(cbuf) { + sign_unplace(id, group, cbuf, 0); } } } + } } /// Jump to a placed sign commands: @@ -1296,13 +1268,7 @@ static void sign_unplace_cmd( /// :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_u *sign_name, int id, char_u *group) { if (sign_name == NULL && group == NULL && id == -1) { EMSG(_(e_argreq)); @@ -1324,21 +1290,13 @@ static void sign_jump_cmd( /// ":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_u *arg, char_u **sign_name, int *signid, + char_u **group, int *prio, buf_T **buf, linenr_T *lnum) { - char_u *arg1; - char_u *name; - char_u *filename = NULL; - int lnum_arg = false; + char_u *arg1; + char_u *name; + char_u *filename = NULL; + int lnum_arg = false; // first arg could be placed sign id arg1 = arg; @@ -1448,7 +1406,7 @@ void ex_sign(exarg_T *eap) } else if (*arg == NUL) { EMSG(_("E156: Missing sign name")); } else { - char_u *name; + char_u *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". @@ -1574,12 +1532,8 @@ list_T *get_buffer_signs(buf_T *buf) } /// 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, - list_T *retlist) +static void sign_get_placed_in_buf(buf_T *buf, linenr_T lnum, int sign_id, const char_u *sign_group, + list_T *retlist) { dict_T *d; list_T *l; @@ -1609,13 +1563,8 @@ static void sign_get_placed_in_buf( /// 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. -void sign_get_placed( - buf_T *buf, - linenr_T lnum, - int sign_id, - const char_u *sign_group, - list_T *retlist -) +void sign_get_placed(buf_T *buf, linenr_T lnum, int sign_id, const char_u *sign_group, + list_T *retlist) { if (buf != NULL) { sign_get_placed_in_buf(buf, lnum, sign_id, sign_group, retlist); @@ -1697,13 +1646,13 @@ void free_signs(void) static enum { - EXP_SUBCMD, // expand :sign sub-commands - EXP_DEFINE, // expand :sign define {name} args - EXP_PLACE, // expand :sign place {id} args - EXP_LIST, // expand :sign place args - EXP_UNPLACE, // expand :sign unplace" - EXP_SIGN_NAMES, // expand with name of placed signs - EXP_SIGN_GROUPS, // expand with name of placed sign groups + EXP_SUBCMD, // expand :sign sub-commands + EXP_DEFINE, // expand :sign define {name} args + EXP_PLACE, // expand :sign place {id} args + EXP_LIST, // expand :sign place args + EXP_UNPLACE, // expand :sign unplace" + EXP_SIGN_NAMES, // expand with name of placed signs + EXP_SIGN_GROUPS, // expand with name of placed sign groups } expand_what; // Return the n'th sign name (used for command line completion) @@ -1740,45 +1689,45 @@ static char_u *get_nth_sign_group_name(int idx) /// Function given to ExpandGeneric() to obtain the sign command /// expansion. -char_u * get_sign_name(expand_T *xp, int idx) +char_u *get_sign_name(expand_T *xp, int idx) { switch (expand_what) { - case EXP_SUBCMD: - return (char_u *)cmds[idx]; - case EXP_DEFINE: { - char *define_arg[] = { "icon=", "linehl=", "text=", "texthl=", "numhl=", - NULL }; - return (char_u *)define_arg[idx]; - } - case EXP_PLACE: { - char *place_arg[] = { "line=", "name=", "group=", "priority=", "file=", - "buffer=", NULL }; - return (char_u *)place_arg[idx]; - } - case EXP_LIST: { - char *list_arg[] = { "group=", "file=", "buffer=", NULL }; - return (char_u *)list_arg[idx]; - } - case EXP_UNPLACE: { - char *unplace_arg[] = { "group=", "file=", "buffer=", NULL }; - return (char_u *)unplace_arg[idx]; - } - case EXP_SIGN_NAMES: - return get_nth_sign_name(idx); - case EXP_SIGN_GROUPS: - return get_nth_sign_group_name(idx); - default: - return NULL; + case EXP_SUBCMD: + return (char_u *)cmds[idx]; + case EXP_DEFINE: { + char *define_arg[] = { "icon=", "linehl=", "text=", "texthl=", "numhl=", + NULL }; + return (char_u *)define_arg[idx]; + } + case EXP_PLACE: { + char *place_arg[] = { "line=", "name=", "group=", "priority=", "file=", + "buffer=", NULL }; + return (char_u *)place_arg[idx]; + } + case EXP_LIST: { + char *list_arg[] = { "group=", "file=", "buffer=", NULL }; + return (char_u *)list_arg[idx]; + } + case EXP_UNPLACE: { + char *unplace_arg[] = { "group=", "file=", "buffer=", NULL }; + return (char_u *)unplace_arg[idx]; + } + case EXP_SIGN_NAMES: + return get_nth_sign_name(idx); + case EXP_SIGN_GROUPS: + 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) { - char_u *end_subcmd; - char_u *last; - int cmd_idx; - char_u *begin_subcmd_args; + char_u *end_subcmd; + char_u *last; + int cmd_idx; + char_u *begin_subcmd_args; // Default: expand subcommands. xp->xp_context = EXPAND_SIGN; @@ -1822,70 +1771,70 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg) // Expand last argument name (before equal sign). xp->xp_pattern = last; switch (cmd_idx) { - case SIGNCMD_DEFINE: - expand_what = EXP_DEFINE; - break; - case SIGNCMD_PLACE: - // List placed signs - if (ascii_isdigit(*begin_subcmd_args)) { - // :sign place {id} {args}... - expand_what = EXP_PLACE; - } else { - // :sign place {args}... - expand_what = EXP_LIST; - } - break; - case SIGNCMD_LIST: - case SIGNCMD_UNDEFINE: - // :sign list <CTRL-D> - // :sign undefine <CTRL-D> - expand_what = EXP_SIGN_NAMES; - break; - case SIGNCMD_JUMP: - case SIGNCMD_UNPLACE: - expand_what = EXP_UNPLACE; - break; - default: - xp->xp_context = EXPAND_NOTHING; + case SIGNCMD_DEFINE: + expand_what = EXP_DEFINE; + break; + case SIGNCMD_PLACE: + // List placed signs + if (ascii_isdigit(*begin_subcmd_args)) { + // :sign place {id} {args}... + expand_what = EXP_PLACE; + } else { + // :sign place {args}... + expand_what = EXP_LIST; + } + break; + case SIGNCMD_LIST: + case SIGNCMD_UNDEFINE: + // :sign list <CTRL-D> + // :sign undefine <CTRL-D> + expand_what = EXP_SIGN_NAMES; + break; + case SIGNCMD_JUMP: + case SIGNCMD_UNPLACE: + expand_what = EXP_UNPLACE; + break; + default: + xp->xp_context = EXPAND_NOTHING; } } else { - // Expand last argument value (after equal sign). + // Expand last argument value (after equal sign). xp->xp_pattern = p + 1; switch (cmd_idx) { - case SIGNCMD_DEFINE: - if (STRNCMP(last, "texthl", 6) == 0 - || STRNCMP(last, "linehl", 6) == 0 - || STRNCMP(last, "numhl", 5) == 0) { - xp->xp_context = EXPAND_HIGHLIGHT; - } else if (STRNCMP(last, "icon", 4) == 0) { - xp->xp_context = EXPAND_FILES; - } else { - xp->xp_context = EXPAND_NOTHING; - } - break; - case SIGNCMD_PLACE: - if (STRNCMP(last, "name", 4) == 0) { - expand_what = EXP_SIGN_NAMES; - } else if (STRNCMP(last, "group", 5) == 0) { - expand_what = EXP_SIGN_GROUPS; - } else if (STRNCMP(last, "file", 4) == 0) { - xp->xp_context = EXPAND_BUFFERS; - } else { - xp->xp_context = EXPAND_NOTHING; - } - break; - case SIGNCMD_UNPLACE: - case SIGNCMD_JUMP: - if (STRNCMP(last, "group", 5) == 0) { - expand_what = EXP_SIGN_GROUPS; - } else if (STRNCMP(last, "file", 4) == 0) { - xp->xp_context = EXPAND_BUFFERS; - } else { - xp->xp_context = EXPAND_NOTHING; - } - break; - default: + case SIGNCMD_DEFINE: + if (STRNCMP(last, "texthl", 6) == 0 + || STRNCMP(last, "linehl", 6) == 0 + || STRNCMP(last, "numhl", 5) == 0) { + xp->xp_context = EXPAND_HIGHLIGHT; + } else if (STRNCMP(last, "icon", 4) == 0) { + xp->xp_context = EXPAND_FILES; + } else { xp->xp_context = EXPAND_NOTHING; + } + break; + case SIGNCMD_PLACE: + if (STRNCMP(last, "name", 4) == 0) { + expand_what = EXP_SIGN_NAMES; + } else if (STRNCMP(last, "group", 5) == 0) { + expand_what = EXP_SIGN_GROUPS; + } else if (STRNCMP(last, "file", 4) == 0) { + xp->xp_context = EXPAND_BUFFERS; + } else { + xp->xp_context = EXPAND_NOTHING; + } + break; + case SIGNCMD_UNPLACE: + case SIGNCMD_JUMP: + if (STRNCMP(last, "group", 5) == 0) { + expand_what = EXP_SIGN_GROUPS; + } else if (STRNCMP(last, "file", 4) == 0) { + xp->xp_context = EXPAND_BUFFERS; + } else { + xp->xp_context = EXPAND_NOTHING; + } + break; + default: + xp->xp_context = EXPAND_NOTHING; } } } @@ -1914,11 +1863,11 @@ int sign_define_from_dict(const char *name_arg, dict_T *dict) goto cleanup; } if (dict != NULL) { - icon = tv_dict_get_string(dict, "icon" , true); + icon = tv_dict_get_string(dict, "icon", true); linehl = tv_dict_get_string(dict, "linehl", true); - text = tv_dict_get_string(dict, "text" , true); + text = tv_dict_get_string(dict, "text", true); texthl = tv_dict_get_string(dict, "texthl", true); - numhl = tv_dict_get_string(dict, "numhl" , true); + numhl = tv_dict_get_string(dict, "numhl", true); } if (sign_define_by_name((char_u *)name, (char_u *)icon, (char_u *)linehl, @@ -1942,27 +1891,23 @@ cleanup: /// values in 'retlist'. void sign_define_multiple(list_T *l, list_T *retlist) { - int retval; + int retval; - TV_LIST_ITER_CONST(l, li, { - retval = -1; - if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT) { - retval = sign_define_from_dict(NULL, TV_LIST_ITEM_TV(li)->vval.v_dict); - } else { - EMSG(_(e_dictreq)); - } - tv_list_append_number(retlist, retval); - }); + TV_LIST_ITER_CONST(l, li, { + retval = -1; + if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT) { + retval = sign_define_from_dict(NULL, TV_LIST_ITEM_TV(li)->vval.v_dict); + } else { + EMSG(_(e_dictreq)); + } + tv_list_append_number(retlist, retval); + }); } /// Place a new sign using the values specified in dict 'dict'. Returns the sign /// identifier if successfully placed, otherwise returns 0. -int sign_place_from_dict( - typval_T *id_tv, - typval_T *group_tv, - typval_T *name_tv, - typval_T *buf_tv, - dict_T *dict) +int sign_place_from_dict(typval_T *id_tv, typval_T *group_tv, typval_T *name_tv, typval_T *buf_tv, + dict_T *dict) { int sign_id = 0; char_u *group = NULL; diff --git a/src/nvim/state.c b/src/nvim/state.c index 02d63d8ab1..a9f3d67849 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -3,19 +3,18 @@ #include <assert.h> -#include "nvim/lib/kvec.h" - #include "nvim/ascii.h" +#include "nvim/edit.h" +#include "nvim/ex_docmd.h" +#include "nvim/getchar.h" +#include "nvim/lib/kvec.h" #include "nvim/log.h" -#include "nvim/state.h" -#include "nvim/vim.h" #include "nvim/main.h" -#include "nvim/getchar.h" #include "nvim/option_defs.h" -#include "nvim/ui.h" #include "nvim/os/input.h" -#include "nvim/ex_docmd.h" -#include "nvim/edit.h" +#include "nvim/state.h" +#include "nvim/ui.h" +#include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "state.c.generated.h" diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 559a7380eb..760c7c0ecc 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -1703,7 +1703,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con regmmatch_T regmatch; lpos_T pos; reg_extmatch_T *cur_extmatch = NULL; - char_u buf_chartab[32]; // chartab array for syn iskeyword + char_u buf_chartab[32]; // chartab array for syn iskeyword char_u *line; // current line. NOTE: becomes invalid after // looking for a pattern match! @@ -5654,7 +5654,7 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in struct subcommand { char *name; // subcommand name - void (*func)(exarg_T *, int); // function to call + void (*func)(exarg_T *, int); // function to call }; static struct subcommand subcommands[] = diff --git a/src/nvim/testdir/test_eval_stuff.vim b/src/nvim/testdir/test_eval_stuff.vim index f7b6704610..883ba5de3d 100644 --- a/src/nvim/testdir/test_eval_stuff.vim +++ b/src/nvim/testdir/test_eval_stuff.vim @@ -174,6 +174,132 @@ func Test_number_max_min_size() call assert_true(v:numbermax > 9999999) endfunc +func Assert_reg(name, type, value, valuestr, expr, exprstr) + call assert_equal(a:type, getregtype(a:name)) + call assert_equal(a:value, getreg(a:name)) + call assert_equal(a:valuestr, string(getreg(a:name, 0, 1))) + call assert_equal(a:expr, getreg(a:name, 1)) + call assert_equal(a:exprstr, string(getreg(a:name, 1, 1))) +endfunc + +func Test_let_register() + let @" = 'abc' + call Assert_reg('"', 'v', "abc", "['abc']", "abc", "['abc']") + let @" = "abc\n" + call Assert_reg('"', 'V', "abc\n", "['abc']", "abc\n", "['abc']") + let @" = "abc\<C-m>" + call Assert_reg('"', 'V', "abc\r\n", "['abc\r']", "abc\r\n", "['abc\r']") + let @= = '"abc"' + call Assert_reg('=', 'v', "abc", "['abc']", '"abc"', "['\"abc\"']") +endfunc + +func Assert_regput(name, result) + new + execute "silent normal! o==\n==\e\"" . a:name . "P" + call assert_equal(a:result, getline(2, line('$'))) + bwipe! +endfunc + +func Test_setreg_basic() + call setreg('a', 'abcA', 'c') + call Assert_reg('a', 'v', "abcA", "['abcA']", "abcA", "['abcA']") + call Assert_regput('a', ['==', '=abcA=']) + + call setreg('A', 'abcAc', 'c') + call Assert_reg('A', 'v', "abcAabcAc", "['abcAabcAc']", "abcAabcAc", "['abcAabcAc']") + call Assert_regput('a', ['==', '=abcAabcAc=']) + + call setreg('A', 'abcAl', 'l') + call Assert_reg('A', 'V', "abcAabcAcabcAl\n", "['abcAabcAcabcAl']", "abcAabcAcabcAl\n", "['abcAabcAcabcAl']") + call Assert_regput('a', ['==', 'abcAabcAcabcAl', '==']) + + call setreg('A', 'abcAc2','c') + call Assert_reg('A', 'v', "abcAabcAcabcAl\nabcAc2", "['abcAabcAcabcAl', 'abcAc2']", "abcAabcAcabcAl\nabcAc2", "['abcAabcAcabcAl', 'abcAc2']") + call Assert_regput('a', ['==', '=abcAabcAcabcAl', 'abcAc2=']) + + call setreg('b', 'abcB', 'v') + call Assert_reg('b', 'v', "abcB", "['abcB']", "abcB", "['abcB']") + call Assert_regput('b', ['==', '=abcB=']) + + call setreg('b', 'abcBc', 'ca') + call Assert_reg('b', 'v', "abcBabcBc", "['abcBabcBc']", "abcBabcBc", "['abcBabcBc']") + call Assert_regput('b', ['==', '=abcBabcBc=']) + + call setreg('b', 'abcBb', 'ba') + call Assert_reg('b', "\<C-V>5", "abcBabcBcabcBb", "['abcBabcBcabcBb']", "abcBabcBcabcBb", "['abcBabcBcabcBb']") + call Assert_regput('b', ['==', '=abcBabcBcabcBb=']) + + call setreg('b', 'abcBc2','ca') + call Assert_reg('b', "v", "abcBabcBcabcBb\nabcBc2", "['abcBabcBcabcBb', 'abcBc2']", "abcBabcBcabcBb\nabcBc2", "['abcBabcBcabcBb', 'abcBc2']") + call Assert_regput('b', ['==', '=abcBabcBcabcBb', 'abcBc2=']) + + call setreg('b', 'abcBb2','b50a') + call Assert_reg('b', "\<C-V>50", "abcBabcBcabcBb\nabcBc2abcBb2", "['abcBabcBcabcBb', 'abcBc2abcBb2']", "abcBabcBcabcBb\nabcBc2abcBb2", "['abcBabcBcabcBb', 'abcBc2abcBb2']") + call Assert_regput('b', ['==', '=abcBabcBcabcBb =', ' abcBc2abcBb2']) + + call setreg('c', 'abcC', 'l') + call Assert_reg('c', 'V', "abcC\n", "['abcC']", "abcC\n", "['abcC']") + call Assert_regput('c', ['==', 'abcC', '==']) + + call setreg('C', 'abcCl', 'l') + call Assert_reg('C', 'V', "abcC\nabcCl\n", "['abcC', 'abcCl']", "abcC\nabcCl\n", "['abcC', 'abcCl']") + call Assert_regput('c', ['==', 'abcC', 'abcCl', '==']) + + call setreg('C', 'abcCc', 'c') + call Assert_reg('C', 'v', "abcC\nabcCl\nabcCc", "['abcC', 'abcCl', 'abcCc']", "abcC\nabcCl\nabcCc", "['abcC', 'abcCl', 'abcCc']") + call Assert_regput('c', ['==', '=abcC', 'abcCl', 'abcCc=']) + + call setreg('d', 'abcD', 'V') + call Assert_reg('d', 'V', "abcD\n", "['abcD']", "abcD\n", "['abcD']") + call Assert_regput('d', ['==', 'abcD', '==']) + + call setreg('D', 'abcDb', 'b') + call Assert_reg('d', "\<C-V>5", "abcD\nabcDb", "['abcD', 'abcDb']", "abcD\nabcDb", "['abcD', 'abcDb']") + call Assert_regput('d', ['==', '=abcD =', ' abcDb']) + + call setreg('e', 'abcE', 'b') + call Assert_reg('e', "\<C-V>4", "abcE", "['abcE']", "abcE", "['abcE']") + call Assert_regput('e', ['==', '=abcE=']) + + call setreg('E', 'abcEb', 'b') + call Assert_reg('E', "\<C-V>5", "abcE\nabcEb", "['abcE', 'abcEb']", "abcE\nabcEb", "['abcE', 'abcEb']") + call Assert_regput('e', ['==', '=abcE =', ' abcEb']) + + call setreg('E', 'abcEl', 'l') + call Assert_reg('E', "V", "abcE\nabcEb\nabcEl\n", "['abcE', 'abcEb', 'abcEl']", "abcE\nabcEb\nabcEl\n", "['abcE', 'abcEb', 'abcEl']") + call Assert_regput('e', ['==', 'abcE', 'abcEb', 'abcEl', '==']) + + call setreg('f', 'abcF', "\<C-v>") + call Assert_reg('f', "\<C-V>4", "abcF", "['abcF']", "abcF", "['abcF']") + call Assert_regput('f', ['==', '=abcF=']) + + call setreg('F', 'abcFc', 'c') + call Assert_reg('F', "v", "abcF\nabcFc", "['abcF', 'abcFc']", "abcF\nabcFc", "['abcF', 'abcFc']") + call Assert_regput('f', ['==', '=abcF', 'abcFc=']) + + call setreg('g', 'abcG', 'b10') + call Assert_reg('g', "\<C-V>10", "abcG", "['abcG']", "abcG", "['abcG']") + call Assert_regput('g', ['==', '=abcG =']) + + call setreg('h', 'abcH', "\<C-v>10") + call Assert_reg('h', "\<C-V>10", "abcH", "['abcH']", "abcH", "['abcH']") + call Assert_regput('h', ['==', '=abcH =']) + + call setreg('I', 'abcI') + call Assert_reg('I', "v", "abcI", "['abcI']", "abcI", "['abcI']") + call Assert_regput('I', ['==', '=abcI=']) + + " Error cases + call assert_fails('call setreg()', 'E119:') + call assert_fails('call setreg(1)', 'E119:') + call assert_fails('call setreg(1, 2, 3, 4)', 'E118:') + call assert_fails('call setreg([], 2)', 'E730:') + call assert_fails('call setreg(1, 2, [])', 'E730:') + call assert_fails('call setreg("/", ["1", "2"])', 'E883:') + call assert_fails('call setreg("=", ["1", "2"])', 'E883:') + call assert_fails('call setreg(1, ["", "", [], ""])', 'E730:') +endfunc + func Test_curly_assignment() let s:svar = 'svar' let g:gvar = 'gvar' diff --git a/src/nvim/testdir/test_registers.vim b/src/nvim/testdir/test_registers.vim index 53069b3d31..fd8653a2eb 100644 --- a/src/nvim/testdir/test_registers.vim +++ b/src/nvim/testdir/test_registers.vim @@ -283,4 +283,84 @@ func Test_insert_small_delete() bwipe! endfunc +" Test for getting register info +func Test_get_reginfo() + enew + call setline(1, ['foo', 'bar']) + + exe 'norm! "zyy' + let info = getreginfo('"') + call assert_equal('z', info.points_to) + call setreg('y', 'baz') + call assert_equal('z', getreginfo('').points_to) + call setreg('y', { 'isunnamed': v:true }) + call assert_equal('y', getreginfo('"').points_to) + + exe '$put' + call assert_equal(getreg('y'), getline(3)) + call setreg('', 'qux') + call assert_equal('0', getreginfo('').points_to) + call setreg('x', 'quux') + call assert_equal('0', getreginfo('').points_to) + + let info = getreginfo('') + call assert_equal(getreg('', 1, 1), info.regcontents) + call assert_equal(getregtype(''), info.regtype) + + exe "norm! 0\<c-v>e" .. '"zy' + let info = getreginfo('z') + call assert_equal(getreg('z', 1, 1), info.regcontents) + call assert_equal(getregtype('z'), info.regtype) + call assert_equal(1, +info.isunnamed) + + let info = getreginfo('"') + call assert_equal('z', info.points_to) + + bwipe! +endfunc + +" Test for restoring register with dict from getreginfo +func Test_set_register_dict() + enew! + + call setreg('"', #{ regcontents: ['one', 'two'], + \ regtype: 'V', points_to: 'z' }) + call assert_equal(['one', 'two'], getreg('"', 1, 1)) + let info = getreginfo('"') + call assert_equal('z', info.points_to) + call assert_equal('V', info.regtype) + call assert_equal(1, +getreginfo('z').isunnamed) + + call setreg('x', #{ regcontents: ['three', 'four'], + \ regtype: 'v', isunnamed: v:true }) + call assert_equal(['three', 'four'], getreg('"', 1, 1)) + let info = getreginfo('"') + call assert_equal('x', info.points_to) + call assert_equal('v', info.regtype) + call assert_equal(1, +getreginfo('x').isunnamed) + + call setreg('y', #{ regcontents: 'five', + \ regtype: "\<c-v>", isunnamed: v:false }) + call assert_equal("\<c-v>4", getreginfo('y').regtype) + call assert_equal(0, +getreginfo('y').isunnamed) + call assert_equal(['three', 'four'], getreg('"', 1, 1)) + call assert_equal('x', getreginfo('"').points_to) + + call setreg('"', #{ regcontents: 'six' }) + call assert_equal('0', getreginfo('"').points_to) + call assert_equal(1, +getreginfo('0').isunnamed) + call assert_equal(['six'], getreginfo('0').regcontents) + call assert_equal(['six'], getreginfo('"').regcontents) + + let @x = 'one' + call setreg('x', {}) + call assert_equal(1, len(split(execute('reg x'), '\n'))) + + call assert_fails("call setreg('0', #{regtype: 'V'}, 'v')", 'E118:') + call assert_fails("call setreg('0', #{regtype: 'X'})", 'E475:') + call assert_fails("call setreg('0', #{regtype: 'vy'})", 'E475:') + + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim index daebe25466..b140077111 100644 --- a/src/nvim/testdir/test_startup.vim +++ b/src/nvim/testdir/test_startup.vim @@ -27,8 +27,8 @@ func Test_after_comes_later() set guioptions+=M let $HOME = "/does/not/exist" set loadplugins - set rtp=Xhere,Xafter,Xanother - set packpath=Xhere,Xafter + set rtp=Xhere,Xdir/after,Xanother + set packpath=Xhere,Xdir/after set nomore let g:sequence = "" [CODE] @@ -50,8 +50,8 @@ func Test_after_comes_later() call mkdir('Xhere/pack/foo/start/foobar/plugin', 'p') call writefile(['let g:sequence .= "pack "'], 'Xhere/pack/foo/start/foobar/plugin/foo.vim') - call mkdir('Xafter/plugin', 'p') - call writefile(['let g:sequence .= "after "'], 'Xafter/plugin/later.vim') + call mkdir('Xdir/after/plugin', 'p') + call writefile(['let g:sequence .= "after "'], 'Xdir/after/plugin/later.vim') if RunVim(before, after, '') @@ -74,7 +74,7 @@ func Test_after_comes_later() call delete('Xsequence') call delete('Xhere', 'rf') call delete('Xanother', 'rf') - call delete('Xafter', 'rf') + call delete('Xdir', 'rf') endfunc func Test_pack_in_rtp_when_plugins_run() diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index 25f45b8fe6..bc64414ecf 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -41,6 +41,8 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler) UIBridgeData *rv = xcalloc(1, sizeof(UIBridgeData)); rv->ui = ui; rv->bridge.rgb = ui->rgb; + rv->bridge.width = ui->width; + rv->bridge.height = ui->height; rv->bridge.stop = ui_bridge_stop; rv->bridge.grid_resize = ui_bridge_grid_resize; rv->bridge.grid_clear = ui_bridge_grid_clear; diff --git a/src/nvim/vim.h b/src/nvim/vim.h index f61f9a5e01..62536a0600 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -305,18 +305,6 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext() #include "nvim/buffer_defs.h" // buffer and windows #include "nvim/ex_cmds_defs.h" // Ex command defines -// Used for flags in do_in_path() -#define DIP_ALL 0x01 // all matches, not just the first one -#define DIP_DIR 0x02 // find directories instead of files -#define DIP_ERR 0x04 // give an error message when none found -#define DIP_START 0x08 // also use "start" directory in 'packpath' -#define DIP_OPT 0x10 // also use "opt" directory in 'packpath' -#define DIP_NORTP 0x20 // do not use 'runtimepath' -#define DIP_NOAFTER 0x40 // skip "after" directories -#define DIP_AFTER 0x80 // only use "after" directories -#define DIP_LUA 0x100 // also use ".lua" files -#define DIP_DIRFILE 0x200 // find both files and directories - // Lowest number used for window ID. Cannot have this many windows per tab. #define LOWEST_WIN_ID 1000 diff --git a/contrib/uncrustify.cfg b/src/uncrustify.cfg index 1bc6bb02c5..821fbca3fc 100644 --- a/contrib/uncrustify.cfg +++ b/src/uncrustify.cfg @@ -1,4 +1,4 @@ -# Uncrustify-0.73.0-164-c9a58467 +# Uncrustify-0.73.0-181-847f1e99 # # General options @@ -259,7 +259,7 @@ sp_before_byref_func = ignore # ignore/add/remove/force/not_defined # following word. # # Default: force -sp_after_type = ignore # ignore/add/remove/force/not_defined +sp_after_type = force # ignore/add/remove/force/not_defined # Add or remove space between 'decltype(...)' and word, # brace or function call. @@ -447,12 +447,18 @@ sp_before_ellipsis = ignore # ignore/add/remove/force/not_defined # Add or remove space between a type and '...'. sp_type_ellipsis = ignore # ignore/add/remove/force/not_defined +# Add or remove space between a '*' and '...'. +sp_ptr_type_ellipsis = ignore # ignore/add/remove/force/not_defined + # (D) Add or remove space between a type and '?'. sp_type_question = ignore # ignore/add/remove/force/not_defined # Add or remove space between ')' and '...'. sp_paren_ellipsis = ignore # ignore/add/remove/force/not_defined +# Add or remove space between '&&' and '...'. +sp_byref_ellipsis = ignore # ignore/add/remove/force/not_defined + # Add or remove space between ')' and a qualifier such as 'const'. sp_paren_qualifier = ignore # ignore/add/remove/force/not_defined @@ -507,6 +513,12 @@ sp_sizeof_ellipsis = ignore # ignore/add/remove/force/not_defined # Add or remove space between 'sizeof...' and '('. sp_sizeof_ellipsis_paren = ignore # ignore/add/remove/force/not_defined +# Add or remove space between '...' and a parameter pack. +sp_ellipsis_parameter_pack = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between a parameter pack and '...'. +sp_parameter_pack_ellipsis = ignore # ignore/add/remove/force/not_defined + # Add or remove space between 'decltype' and '('. sp_decltype_paren = ignore # ignore/add/remove/force/not_defined @@ -2020,7 +2032,7 @@ nl_constr_colon = ignore # ignore/add/remove/force/not_defined # Whether to collapse a two-line namespace, like 'namespace foo\n{ decl; }' # into a single line. If true, prevents other brace newline rules from turning -# such code into four lines. +# such code into four lines. If true, it also preserves one-liner namespaces. nl_namespace_two_to_one_liner = false # true/false # Whether to remove a newline in simple unbraced if statements, turning them @@ -3279,5 +3291,5 @@ set PREPROC REAL_FATTR_CONST set PREPROC REAL_FATTR_NONNULL_ALL set PREPROC REAL_FATTR_PURE set PREPROC REAL_FATTR_WARN_UNUSED_RESULT -# option(s) with 'not default' value: 62 +# option(s) with 'not default' value: 61 # diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index c49d6405f4..11755a9d97 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -1,8 +1,9 @@ local helpers = require('test.functional.helpers')(after_each) local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq, - ok, feed, insert, eval = helpers.clear, helpers.nvim, helpers.curbuf, + ok, feed, insert, eval, tabpage = helpers.clear, helpers.nvim, helpers.curbuf, helpers.curbuf_contents, helpers.window, helpers.curwin, helpers.eq, - helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval + helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval, + helpers.tabpage local poke_eventloop = helpers.poke_eventloop local curwinmeths = helpers.curwinmeths local funcs = helpers.funcs @@ -11,6 +12,7 @@ local NIL = helpers.NIL local meths = helpers.meths local command = helpers.command local pcall_err = helpers.pcall_err +local assert_alive = helpers.assert_alive -- check if str is visible at the beginning of some line local function is_visible(str) @@ -206,7 +208,7 @@ describe('API/win', function() end) end) - describe('{get,set}_option', function() + describe('nvim_win_get_option, nvim_win_set_option', function() it('works', function() curwin('set_option', 'colorcolumn', '4,3') eq('4,3', curwin('get_option', 'colorcolumn')) @@ -224,6 +226,18 @@ describe('API/win', function() pcall_err(curwin, 'get_option', 'statusline')) eq('', eval('&l:statusline')) -- confirm local value was not copied end) + + it('after switching windows #15390', function() + nvim('command', 'tabnew') + local tab1 = unpack(nvim('list_tabpages')) + local win1 = unpack(tabpage('list_wins', tab1)) + window('set_option', win1, 'statusline', 'window-status') + nvim('command', 'split') + nvim('command', 'wincmd J') + nvim('command', 'wincmd j') + eq('window-status', window('get_option', win1, 'statusline')) + assert_alive() + end) end) describe('get_position', function() @@ -354,13 +368,13 @@ describe('API/win', function() local win = meths.open_win(0, true, { relative='editor', row=10, col=10, width=50, height=10 }) - local tabpage = eval('tabpagenr()') + local tab = eval('tabpagenr()') command('tabprevious') eq(1, eval('tabpagenr()')) meths.win_close(win, false) - eq(1001, meths.tabpage_get_win(tabpage).id) - helpers.assert_alive() + eq(1001, meths.tabpage_get_win(tab).id) + assert_alive() end) end) diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index ff93f88a2d..41c80ab95c 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -351,12 +351,12 @@ describe('startup', function() it("handles the correct order with start packages and after/", function() pack_clear [[ lua _G.test_loadorder = {} vim.cmd "runtime! filen.lua" ]] - eq({'ordinary', 'FANCY', 'ordinary after', 'FANCY after'}, exec_lua [[ return _G.test_loadorder ]]) + eq({'ordinary', 'FANCY', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) end) it("handles the correct order with opt packages and after/", function() pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! superspecial\nruntime! filen.lua" ]] - eq({'ordinary', 'SuperSpecial', 'FANCY', 'SuperSpecial after', 'ordinary after', 'FANCY after'}, exec_lua [[ return _G.test_loadorder ]]) + eq({'ordinary', 'SuperSpecial', 'FANCY', 'FANCY after', 'SuperSpecial after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]]) end) end) diff --git a/test/functional/editor/mode_visual_spec.lua b/test/functional/editor/mode_visual_spec.lua index e9c117a1e5..468ae00e01 100644 --- a/test/functional/editor/mode_visual_spec.lua +++ b/test/functional/editor/mode_visual_spec.lua @@ -14,6 +14,7 @@ describe('visual-mode', function() it("select-mode Ctrl-O doesn't cancel Ctrl-O mode when processing event #15688", function() feed('iHello World<esc>gh<c-o>') eq({mode='vs', blocking=false}, meths.get_mode()) -- fast event + eq({mode='vs', blocking=false}, meths.get_mode()) -- again #15288 eq(2, eval('1+1')) -- causes K_EVENT key eq({mode='vs', blocking=false}, meths.get_mode()) -- still in ctrl-o mode feed('^') diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua index 3b407ce5f5..b5de5cd232 100644 --- a/test/functional/legacy/eval_spec.lua +++ b/test/functional/legacy/eval_spec.lua @@ -600,7 +600,6 @@ describe('eval', function() command([[call ErrExe('call setreg(1)')]]) command([[call ErrExe('call setreg(1, 2, 3, 4)')]]) command([=[call ErrExe('call setreg([], 2)')]=]) - command([[call ErrExe('call setreg(1, {})')]]) command([=[call ErrExe('call setreg(1, 2, [])')]=]) command([=[call ErrExe('call setreg("/", ["1", "2"])')]=]) command([=[call ErrExe('call setreg("=", ["1", "2"])')]=]) @@ -615,8 +614,6 @@ describe('eval', function() Vim(call):E118: Too many arguments for function: setreg Executing call setreg([], 2) Vim(call):E730: using List as a String - Executing call setreg(1, {}) - Vim(call):E731: using Dictionary as a String Executing call setreg(1, 2, []) Vim(call):E730: using List as a String Executing call setreg("/", ["1", "2"]) diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index 4373d17890..8074f91215 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -790,3 +790,511 @@ end]] helpers.assert_alive() end) end) + +describe('decorations: virtual lines', function() + local screen, ns + before_each(function() + clear() + screen = Screen.new(50, 12) + screen:attach() + screen:set_default_attr_ids { + [1] = {bold=true, foreground=Screen.colors.Blue}; + [2] = {foreground = Screen.colors.Cyan4}; + [3] = {background = Screen.colors.Yellow1}; + [4] = {bold = true}; + [5] = {background = Screen.colors.Yellow, foreground = Screen.colors.Blue}; + [6] = {foreground = Screen.colors.Blue}; + [7] = {foreground = Screen.colors.SlateBlue}; + [8] = {background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue}; + [9] = {foreground = Screen.colors.Brown}; + } + + ns = meths.create_namespace 'test' + end) + + local example_text = [[ +if (h->n_buckets < new_n_buckets) { // expand + khkey_t *new_keys = (khkey_t *)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); + h->keys = new_keys; + if (kh_is_map && val_size) { + char *new_vals = krealloc( h->vals_buf, new_n_buckets * val_size); + h->vals_buf = new_vals; + } +}]] + + it('works with one line', function() + insert(example_text) + feed 'gg' + meths.buf_set_extmark(0, ns, 1, 33, { + virt_lines={ {{">> ", "NonText"}, {"krealloc", "Identifier"}, {": change the size of an allocation"}}}; + virt_lines_above=true; + }) + + screen:expect{grid=[[ + ^if (h->n_buckets < new_n_buckets) { // expand | + {1:>> }{2:krealloc}: change the size of an allocation | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + } | + | + ]]} + + feed '/krealloc<cr>' + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + {1:>> }{2:krealloc}: change the size of an allocation | + khkey_t *new_keys = (khkey_t *){3:^krealloc}((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + } | + /krealloc | + ]]} + + -- virtual line remains anchored to the extmark + feed 'i<cr>' + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *) | + {1:>> }{2:krealloc}: change the size of an allocation | + {3:^krealloc}((void *)h->keys, new_n_buckets * sizeof(k| + hkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + {4:-- INSERT --} | + ]]} + + feed '<esc>3+' + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *) | + {1:>> }{2:krealloc}: change the size of an allocation | + {3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k| + hkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + ^char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + | + ]]} + + meths.buf_set_extmark(0, ns, 5, 0, { + virt_lines = { {{"^^ REVIEW:", "Todo"}, {" new_vals variable seems unneccesary?", "Comment"}} }; + }) + -- TODO: what about the cursor?? + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *) | + {3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k| + hkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + buck^ets * val_size); | + {5:^^ REVIEW:}{6: new_vals variable seems unneccesary?} | + h->vals_buf = new_vals; | + } | + | + ]]} + + meths.buf_clear_namespace(0, ns, 0, -1) + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *) | + {3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k| + hkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = {3:krealloc}( h->vals_buf, new_n_| + buck^ets * val_size); | + h->vals_buf = new_vals; | + } | + } | + | + ]]} + end) + + + it('works with text at the beginning of the buffer', function() + insert(example_text) + feed 'gg' + + screen:expect{grid=[[ + ^if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + } | + {1:~ }| + | + ]]} + + meths.buf_set_extmark(0, ns, 0, 0, { + virt_lines={ + {{"refactor(khash): ", "Special"}, {"take size of values as parameter"}}; + {{"Author: Dev Devsson, "}, {"Tue Aug 31 10:13:37 2021", "Comment"}}; + }; + virt_lines_above=true; + right_gravity=false; + }) + + -- placing virt_text on topline does not automatically cause a scroll + screen:expect{grid=[[ + ^if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + } | + {1:~ }| + | + ]], unchanged=true} + + feed '<c-b>' + screen:expect{grid=[[ + {7:refactor(khash): }take size of values as parameter | + Author: Dev Devsson, {6:Tue Aug 31 10:13:37 2021} | + ^if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + | + ]]} + end) + + it('works with text et the end of the buffer', function() + insert(example_text) + feed 'G' + + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + ^} | + {1:~ }| + | + ]]} + + local id = meths.buf_set_extmark(0, ns, 7, 0, { + virt_lines={{{"Grugg"}}}; + right_gravity=false; + }) + + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + ^} | + Grugg | + | + ]]} + + meths.buf_del_extmark(0, ns, id) + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + ^} | + {1:~ }| + | + ]]} + end) + + it('works with a block scrolling up', function() + screen:try_resize(30, 7) + insert("aa\nbb\ncc\ndd\nee\nff\ngg\nhh") + feed 'gg' + + meths.buf_set_extmark(0, ns, 6, 0, { + virt_lines={ + {{"they see me"}}; + {{"scrolling", "Special"}}; + {{"they"}}; + {{"hatin'", "Special"}}; + }; + }) + + screen:expect{grid=[[ + ^aa | + bb | + cc | + dd | + ee | + ff | + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + ^bb | + cc | + dd | + ee | + ff | + gg | + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + ^cc | + dd | + ee | + ff | + gg | + they see me | + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + ^dd | + ee | + ff | + gg | + they see me | + {7:scrolling} | + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + ^ee | + ff | + gg | + they see me | + {7:scrolling} | + they | + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + ^ff | + gg | + they see me | + {7:scrolling} | + they | + {7:hatin'} | + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + ^gg | + they see me | + {7:scrolling} | + they | + {7:hatin'} | + hh | + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + they see me | + {7:scrolling} | + they | + {7:hatin'} | + ^hh | + {1:~ }| + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + {7:scrolling} | + they | + {7:hatin'} | + ^hh | + {1:~ }| + {1:~ }| + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + they | + {7:hatin'} | + ^hh | + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + {7:hatin'} | + ^hh | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + + feed '<c-e>' + screen:expect{grid=[[ + ^hh | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + end) + + it('works with sign and numbercolumns', function() + insert(example_text) + feed 'gg' + command 'set number signcolumn=yes' + screen:expect{grid=[[ + {8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan| + {8: }{9: }d | + {8: }{9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v| + {8: }{9: }oid *)h->keys, new_n_buckets * sizeof(khkey_| + {8: }{9: }t)); | + {8: }{9: 3 } h->keys = new_keys; | + {8: }{9: 4 } if (kh_is_map && val_size) { | + {8: }{9: 5 } char *new_vals = krealloc( h->vals_buf, | + {8: }{9: }new_n_buckets * val_size); | + {8: }{9: 6 } h->vals_buf = new_vals; | + {8: }{9: 7 } } | + | + ]]} + + meths.buf_set_extmark(0, ns, 2, 0, { + virt_lines={ + {{"Some special", "Special"}}; + {{"remark about codes", "Comment"}}; + }; + }) + + screen:expect{grid=[[ + {8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan| + {8: }{9: }d | + {8: }{9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v| + {8: }{9: }oid *)h->keys, new_n_buckets * sizeof(khkey_| + {8: }{9: }t)); | + {8: }{9: 3 } h->keys = new_keys; | + {8: }{9: }{7:Some special} | + {8: }{9: }{6:remark about codes} | + {8: }{9: 4 } if (kh_is_map && val_size) { | + {8: }{9: 5 } char *new_vals = krealloc( h->vals_buf, | + {8: }{9: }new_n_buckets * val_size); | + | + ]]} + + meths.buf_set_extmark(0, ns, 2, 0, { + virt_lines={ + {{"Some special", "Special"}}; + {{"remark about codes", "Comment"}}; + }; + virt_lines_leftcol=true; + }) + screen:expect{grid=[[ + {8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan| + {8: }{9: }d | + {8: }{9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v| + {8: }{9: }oid *)h->keys, new_n_buckets * sizeof(khkey_| + {8: }{9: }t)); | + {8: }{9: 3 } h->keys = new_keys; | + {7:Some special} | + {6:remark about codes} | + {8: }{9: 4 } if (kh_is_map && val_size) { | + {8: }{9: 5 } char *new_vals = krealloc( h->vals_buf, | + {8: }{9: }new_n_buckets * val_size); | + | + ]]} + end) + + + it('works with hard tabs', function() + insert(example_text) + feed 'gg' + meths.buf_set_extmark(0, ns, 1, 0, { + virt_lines={ {{">>", "NonText"}, {"\tvery\ttabby", "Identifier"}, {"text\twith\ttabs"}}}; + }) + screen:expect{grid=[[ + ^if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + {1:>>}{2: very tabby}text with tabs | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + } | + | + ]]} + + command 'set tabstop=4' + screen:expect{grid=[[ + ^if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + {1:>>}{2: very tabby}text with tabs | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + } | + | + ]]} + end) + +end) |