diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-01-10 21:18:12 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-10 21:18:12 +0800 |
commit | 9b1112cf48238260b170b8763b18a02a58159c2a (patch) | |
tree | a4a1c50014b7e1f4d373aa5648054b4cfb879baa | |
parent | 870ca1de52b240926b88f01afa697cd9b119bdac (diff) | |
download | rneovim-9b1112cf48238260b170b8763b18a02a58159c2a.tar.gz rneovim-9b1112cf48238260b170b8763b18a02a58159c2a.tar.bz2 rneovim-9b1112cf48238260b170b8763b18a02a58159c2a.zip |
fix(statuscolumn): fix crashes and clang/PVS warnings (#21725)
-rw-r--r-- | src/nvim/buffer_defs.h | 28 | ||||
-rw-r--r-- | src/nvim/drawline.c | 18 | ||||
-rw-r--r-- | src/nvim/mouse.c | 2 | ||||
-rw-r--r-- | src/nvim/statusline.c | 6 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 7 | ||||
-rw-r--r-- | test/functional/ui/statuscolumn_spec.lua | 25 |
6 files changed, 57 insertions, 29 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 40249c2f9d..c794b88229 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1419,20 +1419,20 @@ struct window_S { typedef struct statuscol statuscol_T; struct statuscol { - int width; // width of the status column - int cur_attr; // current attributes in text - int num_attr; // attributes used for line number - int fold_attr; // attributes used for fold column - int sign_attr[SIGN_SHOW_MAX]; // attributes used for signs - int truncate; // truncated width - bool draw; // draw statuscolumn or not - char fold_text[10]; // text in fold column (%C) - char *sign_text[SIGN_SHOW_MAX]; // text in sign column (%s) - char text[MAXPATHL]; // text in status column - char *textp; // current position in text - size_t text_len; // length of text - stl_hlrec_t *hlrec; // highlight groups - stl_hlrec_t *hlrecp; // current highlight group + int width; ///< width of the status column + int cur_attr; ///< current attributes in text + int num_attr; ///< attributes used for line number + int fold_attr; ///< attributes used for fold column + int sign_attr[SIGN_SHOW_MAX + 1]; ///< attributes used for signs + int truncate; ///< truncated width + bool draw; ///< draw statuscolumn or not + char fold_text[10]; ///< text in fold column (%C) + char *sign_text[SIGN_SHOW_MAX + 1]; ///< text in sign column (%s) + char text[MAXPATHL]; ///< text in status column + char *textp; ///< current position in text + char *text_end; ///< end of text (the NUL byte) + stl_hlrec_t *hlrec; ///< highlight groups + stl_hlrec_t *hlrecp; ///< current highlight group }; /// Macros defined in Vim, but not in Neovim diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 23ef7400b7..b1cdfe209b 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -450,14 +450,13 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, i stcp->textp = stcp->text; stcp->hlrecp = stcp->hlrec; stcp->cur_attr = stcp->num_attr; - stcp->text_len = strlen(stcp->text); + stcp->text_end = stcp->text + strlen(stcp->text); int fill = stcp->width - width; if (fill > 0) { // Fill up with ' ' - memset(&stcp->text[stcp->text_len], ' ', (size_t)fill); - stcp->text_len += (size_t)fill; - stcp->text[stcp->text_len] = NUL; + memset(stcp->text_end, ' ', (size_t)fill); + *(stcp->text_end += fill) = NUL; } } @@ -476,10 +475,9 @@ static void get_statuscol_display_info(LineDrawState *draw_state, int *char_attr *draw_state = WL_STC; *char_attr = stcp->cur_attr; *pp_extra = stcp->textp; - *n_extrap = stcp->hlrecp->start ? (int)(stcp->hlrecp->start - stcp->textp) - : (int)strlen(*pp_extra); + *n_extrap = (int)((stcp->hlrecp->start ? stcp->hlrecp->start : stcp->text_end) - stcp->textp); // Prepare for next highlight section if not yet at the end - if (stcp->textp + *n_extrap < stcp->text + stcp->text_len) { + if (stcp->textp + *n_extrap < stcp->text_end) { int hl = stcp->hlrecp->userhl; stcp->textp = stcp->hlrecp->start; stcp->cur_attr = hl < 0 ? syn_id2attr(-stcp->hlrecp->userhl) @@ -488,7 +486,7 @@ static void get_statuscol_display_info(LineDrawState *draw_state, int *char_attr *draw_state = WL_STC - 1; } // Skip over empty highlight sections - } while (*n_extrap == 0 && stcp->textp < stcp->text + stcp->text_len); + } while (*n_extrap == 0 && stcp->textp < stcp->text_end); } /// Return true if CursorLineNr highlight is to be used for the number column. @@ -1328,7 +1326,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, draw_state = WL_STC; // Draw the 'statuscolumn' if option is set. if (statuscol.draw) { - if (statuscol.text_len == 0) { + if (statuscol.textp == NULL) { get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr, sign_num_attr, sattrs, foldinfo, extra, &statuscol); if (wp->w_redr_statuscol) { @@ -2823,7 +2821,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (statuscol.draw) { if (row == startrow + 1 || row == startrow + filler_lines) { // Re-evaluate 'statuscolumn' for the first wrapped row and non filler line - statuscol.text_len = 0; + statuscol.textp = NULL; } else { // Otherwise just reset the text/hlrec pointers statuscol.textp = statuscol.text; statuscol.hlrecp = statuscol.hlrec; diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 88103d1888..ee8c553cd5 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -1110,7 +1110,7 @@ retnomove: ? wp->w_winbar_height != 0 : false; - on_statuscol = grid == (col < win_col_off(wp)) + on_statuscol = (grid == (col < win_col_off(wp))) ? *wp->w_p_stc != NUL : false; diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 7d8394e1b4..6857bef810 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -1502,7 +1502,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n case STL_LINE: // Overload %l with v:lnum for 'statuscolumn' - num = strcmp(opt_name, "statuscolumn") == 0 ? get_vim_var_nr(VV_LNUM) + num = opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0 ? get_vim_var_nr(VV_LNUM) : (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? 0L : (long)(wp->w_cursor.lnum); break; @@ -1602,7 +1602,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n case STL_ROFLAG: case STL_ROFLAG_ALT: // Overload %r with v:relnum for 'statuscolumn' - if (strcmp(opt_name, "statuscolumn") == 0) { + if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) { num = get_vim_var_nr(VV_RELNUM); } else { itemisflag = true; @@ -1628,7 +1628,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n bool fold = opt == STL_FOLDCOL; *buf_tmp = NUL; - for (int i = 0; i <= 9; i++) { + for (int i = 0; i <= SIGN_SHOW_MAX; i++) { char *p = fold ? stcp->fold_text : stcp->sign_text[i]; if ((!p || !*p) && *buf_tmp == NUL) { break; diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 98bfb83dbd..aa2f46bb59 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3126,7 +3126,12 @@ describe('API', function() eq('E539: Illegal character <}>', pcall_err(meths.eval_statusline, '%{%}', {})) end) - it('supports %S item', function() + it('supports various items', function() + eq({ str = '0', width = 1 }, + meths.eval_statusline('%l', { maxwidth = 5 })) + command('set readonly') + eq({ str = '[RO]', width = 4 }, + meths.eval_statusline('%r', { maxwidth = 5 })) local screen = Screen.new(80, 24) screen:attach() command('set showcmd') diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua index cdc2cb8746..912c139ae4 100644 --- a/test/functional/ui/statuscolumn_spec.lua +++ b/test/functional/ui/statuscolumn_spec.lua @@ -293,6 +293,31 @@ describe('statuscolumn', function() {2: }{1: │ }aaaaaa | | ]]) + -- Up to 9 signs in a line + command('set signcolumn=auto:9 foldcolumn=auto') + command('sign place 5 line=6 name=piet1 buffer=1') + command('sign place 6 line=6 name=piet2 buffer=1') + command('sign place 7 line=6 name=piet1 buffer=1') + command('sign place 8 line=6 name=piet2 buffer=1') + command('sign place 9 line=6 name=piet1 buffer=1') + command('sign place 10 line=6 name=piet2 buffer=1') + command('sign place 11 line=6 name=piet1 buffer=1') + screen:expect([[ + {2: }{1: 4│>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: │ }aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 3│}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: │ }aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: │ }aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 1│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: │ }aaaaaaaaaaaaaaaaaaaa | + {2:+}{1: 0│ }{3:^+-- 1 line: aaaaaaaaaaaaaaaaa}| + {2: }{1: 1│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: │ }aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: │ }aaaaaaaaaaaaaaaaaaaa | + | + ]]) end) it('works with \'statuscolumn\' clicks', function() |