diff options
author | zeertzjq <zeertzjq@outlook.com> | 2025-01-09 12:49:45 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-09 12:49:45 +0800 |
commit | 5f85e78db3aff1c685779f7506be4d658c5e9cc8 (patch) | |
tree | 764eff09f655fa72d5cc80ca64e7663d4cad1dd8 | |
parent | 19c9572d3626cde8503ee9061fa334b73f257b03 (diff) | |
download | rneovim-5f85e78db3aff1c685779f7506be4d658c5e9cc8.tar.gz rneovim-5f85e78db3aff1c685779f7506be4d658c5e9cc8.tar.bz2 rneovim-5f85e78db3aff1c685779f7506be4d658c5e9cc8.zip |
vim-patch:9.1.0997: too many strlen() calls in drawscreen.c (#31927)
Problem: too many strlen() calls in drawscreen.c
Solution: refactor drawscreen.c and remove calls to strlen(),
make get_keymap_str() (in screen.c) return string length
instead of TRUE/FALSE (John Marriott).
https://github.com/vim/vim/commit/a21240b97debea2e087aee6ad1488b5f075d1259
Co-authored-by: John Marriott <basilisk@internode.on.net>
-rw-r--r-- | src/nvim/buffer.c | 40 | ||||
-rw-r--r-- | src/nvim/digraph.c | 17 | ||||
-rw-r--r-- | src/nvim/drawscreen.c | 4 | ||||
-rw-r--r-- | src/nvim/statusline.c | 103 |
4 files changed, 85 insertions, 79 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 5dcf7d8f49..9e6877cbfa 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3257,8 +3257,8 @@ void fileinfo(int fullname, int shorthelp, bool dont_truncate) n); validate_virtcol(curwin); size_t len = strlen(buffer); - col_print(buffer + len, IOSIZE - len, - (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); + (void)col_print(buffer + len, IOSIZE - len, + (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); } append_arg_number(curwin, buffer, IOSIZE); @@ -3286,13 +3286,13 @@ void fileinfo(int fullname, int shorthelp, bool dont_truncate) xfree(buffer); } -void col_print(char *buf, size_t buflen, int col, int vcol) +int col_print(char *buf, size_t buflen, int col, int vcol) { if (col == vcol) { - vim_snprintf(buf, buflen, "%d", col); - } else { - vim_snprintf(buf, buflen, "%d-%d", col, vcol); + return vim_snprintf(buf, buflen, "%d", col); } + + return vim_snprintf(buf, buflen, "%d-%d", col, vcol); } static char *lasttitle = NULL; @@ -3416,15 +3416,16 @@ void free_titles(void) /// Get relative cursor position in window into "buf[buflen]", in the localized /// percentage form like %99, 99%; using "Top", "Bot" or "All" when appropriate. -void get_rel_pos(win_T *wp, char *buf, int buflen) +int get_rel_pos(win_T *wp, char *buf, int buflen) { // Need at least 3 chars for writing. if (buflen < 3) { - return; + return 0; } linenr_T above; // number of lines above window linenr_T below; // number of lines below window + int len; above = wp->w_topline - 1; above += win_get_fill(wp, wp->w_topline) - wp->w_topfill; @@ -3435,25 +3436,24 @@ void get_rel_pos(win_T *wp, char *buf, int buflen) } below = wp->w_buffer->b_ml.ml_line_count - wp->w_botline + 1; if (below <= 0) { - xstrlcpy(buf, (above == 0 ? _("All") : _("Bot")), (size_t)buflen); + len = vim_snprintf(buf, (size_t)buflen, "%s", (above == 0) ? _("All") : _("Bot")); } else if (above <= 0) { - xstrlcpy(buf, _("Top"), (size_t)buflen); + len = vim_snprintf(buf, (size_t)buflen, "%s", _("Top")); } else { int perc = (above > 1000000 ? (above / ((above + below) / 100)) : (above * 100 / (above + below))); - - char *p = buf; - size_t l = (size_t)buflen; - if (perc < 10) { - // prepend one space - buf[0] = ' '; - p++; - l--; - } // localized percentage value - vim_snprintf(p, l, _("%d%%"), perc); + len = vim_snprintf(buf, (size_t)buflen, _("%s%d%%"), (perc < 10) ? " " : "", perc); } + if (len < 0) { + buf[0] = NUL; + len = 0; + } else if (len > buflen - 1) { + len = buflen - 1; + } + + return len; } /// Append (2 of 8) to "buf[buflen]", if editing more than one file. diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index aaa77f5fcf..326e929fb6 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -2183,22 +2183,22 @@ static void keymap_unload(void) /// @param fmt format string containing one %s item /// @param buf buffer for the result /// @param len length of buffer -bool get_keymap_str(win_T *wp, char *fmt, char *buf, int len) +int get_keymap_str(win_T *wp, char *fmt, char *buf, int len) { char *p; if (wp->w_buffer->b_p_iminsert != B_IMODE_LMAP) { - return false; + return 0; } buf_T *old_curbuf = curbuf; win_T *old_curwin = curwin; + char to_evaluate[] = "b:keymap_name"; curbuf = wp->w_buffer; curwin = wp; - STRCPY(buf, "b:keymap_name"); // must be writable emsg_skip++; - char *s = p = eval_to_string(buf, false, false); + char *s = p = eval_to_string(to_evaluate, false, false); emsg_skip--; curbuf = old_curbuf; curwin = old_curwin; @@ -2209,9 +2209,12 @@ bool get_keymap_str(win_T *wp, char *fmt, char *buf, int len) p = "lang"; } } - if (vim_snprintf(buf, (size_t)len, fmt, p) > len - 1) { + int plen = vim_snprintf(buf, (size_t)len, fmt, p); + xfree(s); + if (plen < 0 || plen > len - 1) { buf[0] = NUL; + plen = 0; } - xfree(s); - return buf[0] != NUL; + + return plen; } diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index f8aeb02229..7f4de9eab8 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -1045,7 +1045,7 @@ int showmode(void) if (State & MODE_LANGMAP) { if (curwin->w_p_arab) { msg_puts_hl(_(" Arabic"), hl_id, false); - } else if (get_keymap_str(curwin, " (%s)", NameBuff, MAXPATHL)) { + } else if (get_keymap_str(curwin, " (%s)", NameBuff, MAXPATHL) > 0) { msg_puts_hl(NameBuff, hl_id, false); } } @@ -1936,7 +1936,7 @@ static void win_update(win_T *wp) pos.lnum += cursor_above ? 1 : -1) { colnr_T t; - pos.col = (colnr_T)strlen(ml_get_buf(wp->w_buffer, pos.lnum)); + pos.col = ml_get_buf_len(wp->w_buffer, pos.lnum); getvvcol(wp, &pos, NULL, NULL, &t); toc = MAX(toc, t); } diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index d47340505a..fe6892cc27 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -96,53 +96,51 @@ void win_redr_status(win_T *wp) get_trans_bufname(wp->w_buffer); char *p = NameBuff; - int len = (int)strlen(p); + int plen = (int)strlen(p); if ((bt_help(wp->w_buffer) || wp->w_p_pvw || bufIsChanged(wp->w_buffer) || wp->w_buffer->b_p_ro) - && len < MAXPATHL - 1) { - *(p + len++) = ' '; + && plen < MAXPATHL - 1) { + *(p + plen++) = ' '; } if (bt_help(wp->w_buffer)) { - snprintf(p + len, MAXPATHL - (size_t)len, "%s", _("[Help]")); - len += (int)strlen(p + len); + plen += snprintf(p + plen, MAXPATHL - (size_t)plen, "%s", _("[Help]")); } if (wp->w_p_pvw) { - snprintf(p + len, MAXPATHL - (size_t)len, "%s", _("[Preview]")); - len += (int)strlen(p + len); + plen += snprintf(p + plen, MAXPATHL - (size_t)plen, "%s", _("[Preview]")); } if (bufIsChanged(wp->w_buffer)) { - snprintf(p + len, MAXPATHL - (size_t)len, "%s", "[+]"); - len += (int)strlen(p + len); + plen += snprintf(p + plen, MAXPATHL - (size_t)plen, "%s", "[+]"); } if (wp->w_buffer->b_p_ro) { - snprintf(p + len, MAXPATHL - (size_t)len, "%s", _("[RO]")); - // len += (int)strlen(p + len); // dead assignment + plen += snprintf(p + plen, MAXPATHL - (size_t)plen, "%s", _("[RO]")); } + (void)plen; - int this_ru_col = MAX(ru_col - (Columns - stl_width), (stl_width + 1) / 2); + int n = (stl_width + 1) / 2; + int this_ru_col = ru_col - (Columns - stl_width); + this_ru_col = MAX(this_ru_col, n); if (this_ru_col <= 1) { p = "<"; // No room for file name! - len = 1; + plen = 1; } else { int i; // Count total number of display cells. - int clen = (int)mb_string2cells(p); + plen = (int)mb_string2cells(p); // Find first character that will fit. // Going from start to end is much faster for DBCS. - for (i = 0; p[i] != NUL && clen >= this_ru_col - 1; + for (i = 0; p[i] != NUL && plen >= this_ru_col - 1; i += utfc_ptr2len(p + i)) { - clen -= utf_ptr2cells(p + i); + plen -= utf_ptr2cells(p + i); } - len = clen; if (i > 0) { p = p + i - 1; *p = '<'; - len++; + plen++; } } @@ -152,16 +150,17 @@ void win_redr_status(win_T *wp) int width = grid_line_puts(off, p, -1, attr); grid_line_fill(off + width, off + this_ru_col, fillchar, attr); - if (get_keymap_str(wp, "<%s>", NameBuff, MAXPATHL) - && this_ru_col - len > (int)strlen(NameBuff) + 1) { - grid_line_puts(off + this_ru_col - (int)strlen(NameBuff) - 1, NameBuff, -1, attr); + int NameBufflen = get_keymap_str(wp, "<%s>", NameBuff, MAXPATHL); + if (NameBufflen > 0 && this_ru_col - plen > NameBufflen + 1) { + grid_line_puts(off + this_ru_col - NameBufflen - 1, NameBuff, -1, attr); } win_redr_ruler(wp); // Draw the 'showcmd' information if 'showcmdloc' == "statusline". if (p_sc && *p_sloc == 's') { - const int sc_width = MIN(10, this_ru_col - len - 2); + n = this_ru_col - plen - 2; // perform the calculation here so we only do it once + const int sc_width = MIN(10, n); if (sc_width > 0) { grid_line_puts(off + this_ru_col - sc_width - 1, showcmd_buf, sc_width, attr); @@ -548,36 +547,40 @@ void win_redr_ruler(win_T *wp) #define RULER_BUF_LEN 70 char buffer[RULER_BUF_LEN]; - // Some sprintfs return the length, some return a pointer. - // To avoid portability problems we use strlen() here. - vim_snprintf(buffer, RULER_BUF_LEN, "%" PRId64 ",", - (wp->w_buffer->b_ml.ml_flags & - ML_EMPTY) ? 0 : (int64_t)wp->w_cursor.lnum); - size_t len = strlen(buffer); - col_print(buffer + len, RULER_BUF_LEN - len, - empty_line ? 0 : (int)wp->w_cursor.col + 1, - (int)virtcol + 1); + int bufferlen = vim_snprintf(buffer, RULER_BUF_LEN, "%" PRId64 ",", + (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) + ? 0 + : (int64_t)wp->w_cursor.lnum); + bufferlen += col_print(buffer + bufferlen, RULER_BUF_LEN - (size_t)bufferlen, + empty_line ? 0 : (int)wp->w_cursor.col + 1, + (int)virtcol + 1); // Add a "50%" if there is room for it. // On the last line, don't print in the last column (scrolls the // screen up on some terminals). - int i = (int)strlen(buffer); - get_rel_pos(wp, buffer + i + 1, RULER_BUF_LEN - i - 1); - int o = i + vim_strsize(buffer + i + 1); + char rel_pos[RULER_BUF_LEN]; + int rel_poslen = get_rel_pos(wp, rel_pos, RULER_BUF_LEN); + int n1 = bufferlen + vim_strsize(rel_pos); if (wp->w_status_height == 0 && !is_stl_global) { // can't use last char of screen - o++; + n1++; } + + int this_ru_col = ru_col - (Columns - width); // Never use more than half the window/screen width, leave the other half // for the filename. - int this_ru_col = MAX(ru_col - (Columns - width), (width + 1) / 2); - if (this_ru_col + o < width) { - // Need at least 3 chars left for get_rel_pos() + NUL. - while (this_ru_col + o < width && RULER_BUF_LEN > i + 4) { - i += (int)schar_get(buffer + i, fillchar); - o++; - } - get_rel_pos(wp, buffer + i, RULER_BUF_LEN - i); + int n2 = (width + 1) / 2; + this_ru_col = MAX(this_ru_col, n2); + if (this_ru_col + n1 < width) { + // need at least space for rel_pos + NUL + while (this_ru_col + n1 < width + && RULER_BUF_LEN > bufferlen + rel_poslen + 1) { // +1 for NUL + bufferlen += (int)schar_get(buffer + bufferlen, fillchar); + n1++; + } + bufferlen += vim_snprintf(buffer + bufferlen, RULER_BUF_LEN - (size_t)bufferlen, + "%s", rel_pos); } + (void)bufferlen; if (ui_has(kUIMessages) && !part_of_status) { MAXSIZE_TEMP_ARRAY(content, 1); @@ -595,11 +598,11 @@ void win_redr_ruler(win_T *wp) did_show_ext_ruler = false; } // Truncate at window boundary. - o = 0; - for (i = 0; buffer[i] != NUL; i += utfc_ptr2len(buffer + i)) { - o += utf_ptr2cells(buffer + i); - if (this_ru_col + o > width) { - buffer[i] = NUL; + for (n1 = 0, n2 = 0; buffer[n1] != NUL; n1 += utfc_ptr2len(buffer + n1)) { + n2 += utf_ptr2cells(buffer + n1); + if (this_ru_col + n2 > width) { + bufferlen = n1; + buffer[bufferlen] = NUL; break; } } @@ -1536,7 +1539,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op // Store the position percentage in our temporary buffer. // Note: We cannot store the value in `num` because // `get_rel_pos` can return a named position. Ex: "Top" - get_rel_pos(wp, buf_tmp, TMPLEN); + (void)get_rel_pos(wp, buf_tmp, TMPLEN); str = buf_tmp; break; @@ -1564,7 +1567,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op case STL_KEYMAP: fillable = false; - if (get_keymap_str(wp, "<%s>", buf_tmp, TMPLEN)) { + if (get_keymap_str(wp, "<%s>", buf_tmp, TMPLEN) > 0) { str = buf_tmp; } break; |