diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/popupmenu.c | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index 3860ba8f6a..b057cae08d 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -803,14 +803,25 @@ static void pum_preview_set_text(buf_T *buf, char *info, linenr_T *lnum, int *ma Error err = ERROR_INIT; Arena arena = ARENA_EMPTY; Array replacement = ARRAY_DICT_INIT; - char *token = NULL; - char *line = os_strtok(info, "\n", &token); buf->b_p_ma = true; - while (line != NULL) { - ADD(replacement, STRING_OBJ(cstr_to_string(line))); + + // Iterate through the string line by line by temporarily replacing newlines with NUL + for (char *curr = info, *next; curr; curr = next ? next + 1 : NULL) { + if ((next = strchr(curr, '\n'))) { + *next = NUL; // Temporarily replace the newline with a string terminator + } + // Only skip if this is an empty line AND it's the last line + if (*curr == '\0' && !next) { + break; + } + + *max_width = MAX(*max_width, (int)mb_string2cells(curr)); + ADD(replacement, STRING_OBJ(cstr_to_string(curr))); (*lnum)++; - (*max_width) = MAX(*max_width, (int)mb_string2cells(line)); - line = os_strtok(NULL, "\n", &token); + + if (next) { + *next = '\n'; + } } int original_textlock = textlock; @@ -828,8 +839,23 @@ static void pum_preview_set_text(buf_T *buf, char *info, linenr_T *lnum, int *ma buf->b_p_ma = false; } +/// Calculate the total height (in screen lines) of the first 'count' buffer lines in window 'wp'. +/// Takes line wrapping and other display factors into account. +/// +/// @param wp Window pointer +/// @param count Number of buffer lines to measure (1-based) +/// @return Total height in screen lines +static inline int pum_preview_win_height(win_T *wp, linenr_T count) +{ + int height = 0; + for (int i = 1; i <= count; i++) { + height += plines_win(wp, i, false); + } + return height; +} + /// adjust floating info preview window position -static void pum_adjust_info_position(win_T *wp, int height, int width) +static void pum_adjust_info_position(win_T *wp, int width) { int col = pum_col + pum_width + pum_scrollbar + 1; // TODO(glepnir): support config align border by using completepopup @@ -850,8 +876,10 @@ static void pum_adjust_info_position(win_T *wp, int height, int width) } // when pum_above is SW otherwise is NW wp->w_config.anchor = pum_above ? kFloatAnchorSouth : 0; - wp->w_config.row = pum_above ? pum_row + height : pum_row; - wp->w_config.height = MIN(Rows, height); + linenr_T count = wp->w_buffer->b_ml.ml_line_count; + wp->w_width_inner = wp->w_config.width; + wp->w_config.height = MIN(Rows, pum_preview_win_height(wp, count)); + wp->w_config.row = pum_above ? pum_row + wp->w_config.height : pum_row; wp->w_config.hide = false; win_config_float(wp, wp->w_config); } @@ -884,10 +912,7 @@ win_T *pum_set_info(int selected, char *info) RedrawingDisabled--; redraw_later(wp, UPD_NOT_VALID); - if (wp->w_p_wrap) { - lnum += plines_win(wp, lnum, true); - } - pum_adjust_info_position(wp, lnum, max_info_width); + pum_adjust_info_position(wp, max_info_width); unblock_autocmds(); return wp; } @@ -1063,11 +1088,8 @@ static bool pum_set_selected(int n, int repeat) curwin->w_cursor.col = 0; if (use_float) { - if (curwin->w_p_wrap) { - lnum += plines_win(curwin, lnum, true); - } // adjust floating window by actually height and max info text width - pum_adjust_info_position(curwin, lnum, max_info_width); + pum_adjust_info_position(curwin, max_info_width); } if ((curwin != curwin_save && win_valid(curwin_save)) |