aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/popupmenu.c56
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))